" C ++之间的差异无效指针"和" C#var"

时间:2015-01-01 06:49:29

标签: c# c++

在学习C#时,我想到了这个问题。 voidvar之间有什么区别? 以下是我想分享的两个例子:

void * voidInt = (void *) 7;
void * voidChar = (void *) 'F';
void * voidCharArray = (void *) "AbcString";

这是var的例子:

var varInt = 7;
var varChar = 'F';
var varCharArray = "AbcString";
  • void匿名数据类型吗?
  • 如果是,那么主要是什么 varvoid之间的差异?

有人可以帮助我清除这种情况吗?

4 个答案:

答案 0 :(得分:32)

这里的其他答案都相当不错,但我认为他们没有清楚地了解基本面。这是你困惑的基本原则,所以让我们解决这些问题。

  • 变量存储位置,其中包含
  • 变量类型相关联。
  • 本地变量具有名称

所以voidIntvoidCharvoidCharArrayvarIntvarCharvarCharArray都是变量,它们都有类型与它们相关联。每个变量都可以分配该类型的值,或生成该类型的值,具体取决于是否正在写入或读取变量。

好的,现在指针是什么?

  • 类型具有相应的指针类型。 (请注意,在不安全的C#中,只有非托管类型具有相应的指针类型。)
  • void *类型是一种特殊的指针类型。
  • 指针是一个值。
  • 类型为T*的指针可以取消引用以生成类型为T变量T*不得为void*
  • 指针可以显式转换为任何整数类型,但允许这些操作丢失信息并依赖于实现细节。
  • 任何指针值都可以隐式转换为void*
  • 任何void*值都可以显式转换为任何指针类型值。

C#中的var是什么?

  • var是一种"语法糖"告诉编译器从initialzier推导出变量的类型,而不是要求它被写出来。

什么是"匿名类型"在C#?

  • C#中的某些表达式具有未声明且没有名称的类型;这些被称为" anonymous"类型。

现在我们可以看一下你的程序,看看每行的作用。

void * voidInt = (void *) 7;

voidIntvoid*类型的变量。分配给它的值是整数7到指针的转换,这几乎可以肯定是任何现代操作系统上的垃圾指针。这段代码基本上是荒谬的。

更明智的代码是:

int myInt = 7;
int* intPtr = &myInt;
void* voidInt = intPtr;

这意味着myInt是一个保存值7的变量,intPtr是一个保存指针的变量;当该指针被解除引用时,它产生变量myIntvoidInt是一个包含任何指针的变量,从intPtr读取的值是一个指针。所以现在voidIntintPtr都有一个指向变量myInt的指针。

void * voidChar = (void *) 'F';

这里也是一样的。字符F被视为数字并转换为指针值,该值存储在变量中。这不明智。明智的代码将是这样的:

char myChar = 'F';
void *voidChar = &myChar;

但这很有道理:

void * voidCharArray = (void *) "AbcString";

C ++中的字符串文字可转换为char*,它是指向第一个字符的存储的指针,该指针可转换为void*

这个怎么样?

var varInt = 7;
var varChar = 'F';
var varCharArray = "AbcString";

这只是一种令人愉快的写作方式

int varInt = 7;
char varChar = 'F';
string varCharArray = "AbcString";

每个变量都有给定的类型,每个赋值都在变量中存储该类型的值。

匿名类型怎么样?

var anon = new { X = 123, Y = 456 };

这使得匿名类型的变量,其中匿名类型具有两个属性X和Y,类型int。该类型没有名称,因此无法在声明中写出类型,因此必须使用var

这里的关键是要确保你掌握基础:指针是,它们可能是解除引用,这样做会产生一个变量。由于指针是,它们本身可以存储在指针类型的变量中。这几乎与var无关,这在C#中是一种令人愉快的方式,使编译器能够确定变量应该具有的类型。

答案 1 :(得分:18)

voidvar并没有任何共同之处:

  • void(由C和C ++中的指针变量使用)表示未指定(非确定)类型。在托管C#中不允许void*(尽管非常弱的类型,例如object引用可能是近似的)。通常,需要重新构建void*类型才能使用。

  • 但是,方法/函数中的void 返回类型意味着相同 用两种语言表示没有返回值(如Scala中的Unit

  • 相比之下,C#中的var定义了implicitly typed variable - 变量仍然具有强类型,但实际类型是在编译时从右侧推断的。

e.g。

var v1 = "Foo"; // v1 is a string, because it is inferred from the right hand side
var v2 = XDocument.Parse(@"c:\temp\foo.xml"); // v2 is the return type of the function
使用匿名类型时经常需要

var - 这可能是您在var和匿名类型之间建立连接的地方:

var v3 = new { Name = "Foo", Value = 123};  // v3 is strongly typed, anonymous class.

var对于将变量赋值给LINQ表达式的返回值特别有用,其中类型可能非常复杂:

var v3 = db.Persons
      .Join(db.Cities, p => p.CityId, c => c.Id, (p, c) => new {Person = p, City = c})
      .GroupBy(pc => pc.City.Name);

*实际上,这并不完全正确,您可以在C#中使用void * unsafe

修改

另外值得一提的是,从C#6开始,隐式var输入只能用于局部变量,即C#不支持隐式输入方法返回类型(与Scala等函数式语言不同) ,大多数情况下编译器也可以推断出方法的返回类型。)

答案 2 :(得分:7)

  • 在不安全的上下文中,C#中的C ++ void*相当于void*。可以将任何数据指针类型分配给void*
  • 在安全的环境中,object(松散地)是相应的概念。可以为其分配任何类/接口/结构实例。
  • C ++中C#var的等价物是auto。当用于声明和初始化局部变量时,它可以作为分配给该变量的表达式的类型(如果可能的话)。

答案 3 :(得分:3)

您可以使用c ++ void pointer:

执行此操作
void * val = (void *) 7;
val = (void *) "Abcd";

但你不能用c#var:

这样做
var val = 7;
val = "abcd";

这会引发错误。

更新

如果您希望实现void *的类似行为,可以使用dynamic

dynamic val = (dynamic) 7;
val = (dynamic) "ABC";

使用var时,变量的实际类型在编译时确定。但是,当使用dynamic时,变量的实际类型是在运行时确定的。