C语言中out和ref的区别是什么?

作者&投稿:潮健 (若有异议请与网页底部的电邮联系)
c# ref与c语言的指针能互传吗~

严格来说不可以!
这里边有几个错误的理解需要纠正一下:
来格来说int是属于.net的,int是Int32的别名,也就是32bits的数字,当然,short是Int16的别名,long是Int64的别名,如果说C#语言的话,可以说Int32,一般情况下我们再不区分int与Int32的区别。而C语言中的int却并不是32bits数,而是16bit数!换句话来说,如果是平台调用(PInovke)的话,一般我们用C#中的short来接C语言中的int!
当然,如果指针类似值的话,一定要了解平台调用部分的数据封送!数据封送部分介绍了平台之间数据如果对接的,这部分的知识一定要理解。但是有时只有一个参数时,大多数我们会使用C#语言中自动转换的方式,比如使用C#中int去接C语言中int中的值是没有问题的(C#会把short自动转换为int).
但是,对于结构(struct)之类的,由于其中包含多个值,所以对于对象进行平台封送时,一定要使用相应的形式(其实是内存数据的重新包装而已),如果要使用特定的数据形式,一定要使用特性化编程中的位节说明来说明字体的长度(比如在接值的时候string接值时就必段说明内存段大小)。
第二个问题是关于ref或out的,ref只是传址引用,并不是指针(一定一定不要用指针这个词,因为在.net中除值类型valuetype和引用值类型object之外,在非安全编程unsafe下是存在指针的!)其实呢,无论是引用类型或是值类型的参数,传入的都是一个值(值类型)或副本(浅表复制),而ref/out是传址引用,在托管代码下,ref/out表示的传址引用,与指针还是有区别的!你可以认为他是一种隐藏的指针方式(*与&是配对的,这才是指针,传入的是一个真实的逻辑地址),而ref/out并不是把指针进行了打包,而是将址进行了堆栈查找。换句话来说,指针传入的是一个逻辑地址,而ref则告诉调用查询你自己去这个变量的地址去改变——再说传统一点(就是教学书上标准的说法)就是传入的是对象并不是副本了(我们说正常的参数是一个对象的副本)!
第三个问题,也是关于ref/out的,一定要记着,如果第二个问题你理解了,第三个问题其实是不是犯错的!关于参数签名中含有ref/out的话,那么调用时一定要使用ref来表现参数!比如set(ref int x)在调用时一定要使用set(ref x);而不能是set(x),否则只是传入副本(值)所以,int x = 0; set(x);方法是错误的,应该是set(ref x);否则会出现无法配置签名(找不到方法)的例外。
至于最后一个,那么就是指针互传这个称呼是多么错误的!关于非安全编程,是否存在指针互传的问题也不是正确的。所以关于指针来说,两种语言的指针都是各自所指,并没有脱离语言本身的存在,所以这两个指针互传在语言层面之外,并不存在这样的称呼。
所以这里你如果将set(x)改为set(ref x)应该可以执行——如果不能执行,有执行错误(注意平台调用发生错误时,由于非托管的错误你只能拿到托管错误,并不能拿到真实的错误原因),将int改为short,然后就可以了!

  C#中ref 关键字使参数按引用传递。 其效果是,当控制权传递回调用方法时,在方法中对参数的任何更改都将反映在该变量中。
  注意:不要将“通过引用传递”概念与“引用类型”概念相混淆。 这两个概念不相关;方法参数无论是值类型还是引用类型,都可通过 ref 进行修饰。 因此,通过引用传递值类型时没有值类型装箱。
  若要使用 ref 参数,则方法定义和调用方法都必须显式使用 ref 关键字。例如:
class RefExample { staticvoid Method(refint i) { i = 44; } staticvoid Main() { int val = 0; Method(ref val); // val is now 44 } }

ref:相当于c语言的引用参数  实参和形参一起变。

out:多用于输出参数  就是在return之前必须给out标示的参数赋值。



还是以例子来说明吧;
1. ref:
int i =0;
有函数fun(ref i)和fun(i)
它们的函数体都是{ i = 3;},那么在执行以下两段代码后:
(1)int i = 0; fun(i); System.Console.WriteLine(i.ToString());
(2)int i = 0; fun(ref i); System.Console.WriteLine(i.ToString());
(1)的输出是1,(2)的输出是3,

2. out:
int i; //注意,这里只是声明了变量i,并没有对其初始化
有函数fun(ref i)、fun(out i)和fun(i)
它们的函数体都是{ i = 3;},那么在执行以下三段代码后:
(1)int i = 0; fun(i); System.Console.WriteLine(i.ToString());
(2)int i = 0; fun(ref i); System.Console.WriteLine(i.ToString());
(3)int i = 0; fun(out i); System.Console.WriteLine(i.ToString());
(1)和(2)在编译的时候都会报错:错误 CS0165: 使用了未赋值的局部变量“i”
而(3)能正常编译,而且输出3

最后总结一下:
Ref和Out这两个关键字都能够提供相似的功效,其作用也很像C中的指针变量。稍有不同之处是:
使用Ref型参数时,传入的参数必须先被初始化。而Out则不需要,对Out而言,就必须在方法中对其完成初始化。
使用Ref和Out时都必须注意,在方法的参数和执行方法时,都要加Ref或Out关键字。以满足匹配。
Out更适合用在需要Return多个返回值的地方,而Ref则用在需要被调用的方法修改调用者的引用的时候。

在C语言中,ref相当于c语言的引用参数,实参和形参一起变。out多用于输出参数,就是在return之前必须给out标示的参数赋值。这就是out和ref的区别。



  out与ref的区别如下:
  private void button1_Click(object sender, EventArgs e)
  {
  //ref,out都能修改传进来的参数的值。
  int refInt = 100;
  RefValue(ref refInt);
  MessageBox.Show(refInt.ToString());
  //
  int outInt = 100;
  outValue(out outInt, 100);
  MessageBox.Show(outInt.ToString());
  }
  //ref
  public void RefValue(ref int refInt)
  {
  refInt += 100;//ref引用不需要初始化
  }
  //一个函数可以有多个ref参数
  public void RefValue(ref int refInt,ref int rInt)
  {
  refInt += 100;//ref引用不需要初始化
  }
  //out
  public void outValue(out int outInt, int i)
  {
  outInt = i + 100;//out引用必须初始化
  }
  /*函数不可以有多个out参数
  public void outValue(out int outInt, out oInt,int i)
  {
  outInt = i + 100;//out引用必须初始化
  }*/

求一个用c语言编的奖金系统,条件如下 高手们谢谢了
答://teach level#define LEVELA 0#define LEVELB 1#define LEVELC 2//max week in one year#define MAXWEEK 54 // 366/7=52.4==53 53+1=54#define MAXCLASS 10000 //max class in one year#define MAXCLASSINFO 3//ref reward#define STANDREWARD 0#define OUTREWARD 1//ref class...

c语言问题,圈起来的那个,,,没看懂
答:全面给你解读下吧:前文意思是强调定义过程中是无效的,定义后才有效!本文中 typedef 当前结构体类型为 SELF_REF3,即SELF_REF3与struct SELF_REF3_TAG 相等。(具体参考百度百科typedef 用法)b的意思是SELF_REF3 类型的指针。但是注意前面的例子中,还没typedef完成,在定义typedef 为 SELF_REF3过程...

C语言中,用"->"和用"."的区别
答:c语言中绝对有“->”和“.”!这两个运算符都是用来访问结构体的。比如有结构体 struct student { int math;int english;};并且有两个变量 struct student zhangsan;struct student *p;p=&zhangsan;你要留意zhangsan是结构体的名字,p是指向这个结构体的指针。那么访问结构体的两个变量时就只能用 z...

C语言中指针的用法。
答:void PushBtnHandler(void *CallBackRef)这是一个void类型的函数,即返回值为空,传入的参数是void *(CallBackRef这个类型就死void *)int *pPushBtn = (int *)CallBackRef;对于这句,定义一个int类型的指针,而CallBackRef是void *型的,所以用 (int *)类型转换转成int *型给pPushBtn int...

到底如何在spring中使用redis
答:1. Redis使用场景 Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。我们都知道,在日常的应用中,数据库瓶颈是最容易出现的。数据量太大和频繁的查询,由于磁盘IO性能的局限性,导致项目的性能越来越低。这时候,基于内存的缓存...

c# ref与c语言的指针能互传吗
答:c++既然已经学了,学c就能相对快点了,c的书多少还是要看看的,能不能过这个要看出的考题你会不会了,会就能过,不会就不能。虽然c和c++语法很像,虽然c++及其编译器兼容c语言的库和可内嵌asm,虽然c++也有c的面向过程设计范型,虽然你可以把c++的c部分当c语言来用。但是你要把c++当成和c是不同的...

关于c语言指针赋值的问题
答:好吧,我来回答你:1, get()=newRef;//编译出错 答: get()函数返回的是一个常量指针,在C中,常量不能用作左值,所以出错 2, void *oldref=get();oldref=newRef;后来我一想,这么做,不只是操纵了oldref,而不是操纵get函数得来的ref了吗?答: 你的想法是正确的,可以这样做,把get(...

...的DAC转换在P0_1脚有0~3.3V电压输出,用C语言怎么写,求大神解答_百 ...
答:P0MDOUT |= 0x10; // Enable TX0 as a push-pull output P0MDIN &= ~0xCF; // Set desired pins as analog inputs } void ADC0_Init (void){ ADC0CN = 0x02; // ADC0 disabled, normal tracking,// conversion triggered on TMR2 overflow REF0CN = 0x03; // Enab...

C# 错误代码为 0xc0000005
答:在网上查到这样一句话 c语言编译的库char*的参数接收的是数组的起始地址,不论什么类型的数组,传递时实际上都是按引用传递,所以不需要再用ref修饰,否则会出错 按道理说要这样传递 Byte[] bytes = new Byte[256];foo(ref bytes[0]);但是一般char*的参数要用C#里的StringBuilder对象传递是没问题的...

C# 调用C语言接口问题
答:没错就是传值的问题 最后一个string传递不正确,很可能被当作Unicode传进去了 DllImport属性里加上 CharSet=CharSet.Ansi [System.Runtime.InteropServices.DllImport("Sign.dll", CharSet=CharSet.Ansi)]