编译器如何处理数据类型?
How does compiler treat datatype?
如果指针指向特定数据类型,编译器如何知道(翻译)该特定数据类型的所有属性(大小,...,其他是什么?)?
如果我有例如:
char* foo[] = {"abc", "123", "def"};
,那么编译器必须创建双指针(指向指针的指针)才能拥有这个(地址)数组(字符)数组。
但为什么不是数据类型 void*
(因为它是寻址 - 地址数据类型是空的 - 到字符串),而不是数据类型 char
?
按照我现在的理解——无论它必须取消引用多少个地址(char**、char***、...),声明的数据类型都是针对最终找到的 VALUE。所以我将其理解为路径中的 'backstop',通过检查 最终值 大小找到实际值。因此,一旦编译器取消引用所有引用 - 它创建的路径 - 然后它只知道它找到了值,因为它是一个字节长并且以空字符终止 - 就像 char 一样(而不是继续取消引用一个地址,它是 8 个字节长)。
所以问题是,编译器如何知道特定的数据类型。 属性 编译器决定它是什么以及它有多长。它对其他事情做出决定吗?还是我的观念正确?
PS: 本例中不需要指针运算。
(as it is addressing -address datatype is void - to string)
foo
是指向字符的指针数组。 (不是双指针)
foo
中的元素是指向字符的指针(写作char*
)。那是数组中元素的类型。数组中的元素不是void*
,而是char*
。所以数组中元素的类型写成char*
.
char*
表示 "pointer to char
" 但 char*
本身 也是 一个完全有效的数据类型。它与 void*
不同。您可以有指向 char*
(写作 char**
)的指针,char*
的数组,等等。
...那么编译器必须制作双指针(指向指针的指针).
编译器 必须 在这种情况下创建一个 char ** 是不正确的。编译器将简单地将 char* foo[] = {"abc", "123", "def"};
视为一个由 3 个指针组成的数组,并使用字符串文字进行初始化。
但是,是正确的是,如果将同一个变量作为函数参数传递,则只有每个数组的第一个元素的地址会有效传递,从而导致您指向指针断言的指针。可以将此变量作为参数传递的函数原型包括:
void func2(char *a[]);
void func2(char *a[3]);
void func3(char **a, int order);//includes size information
因此给定 foo
如上定义,将按如下方式进行调用:
func2(foo);
func3(foo, 3);// requires size information
foo
的两个实例在被调用函数处理时都将被视为 char **
。
但为什么不是数据类型 void*...
简而言之,void *
是一种在程序员方面允许 type
歧义的方法。反之,如果使用得当,编译时就不会出现歧义。 (如果有,好的编译器会发出警告或错误。)。
在 C 中,关键字 void
的使用受到限制:
作为函数使用时return类型,表示函数
没有 return 值。
当它出现在指针声明中时,它指定
指针是通用的。
在函数的参数列表中使用时,void 表示
函数不带参数。
使用列表不包括创建非指针变量,如
void variable = s;// Illegal, creates a compile-time error.
但是,void *
对于处理可能作为函数参数传递的各种数据类型很有用。例如,给定:
typedef union {
int a;
char b;
float c;
double d;
} TYP;
TYP typ;
enum {
INT,
CHAR,
FLT,
DBL
}
void func4(void *a, int type)// void * provides type ambiguity in argument 1
{ //i.e. programmer can pass int, char or double
switch(type) {
case 0://int
typ.a = (int)a;
break;
case 1://char
typ.b = (char)a;
break;
case 2://float
typ.c = *(float *)(a);
break;
case 3://double
typ.d = *(double *)(a);
break;
};
}
附调用示例:
char c = 'P';
int d = 1024;
float e = 14.5;
double f = 0.0000012341;
func4(&c, CHAR);
func4(&d, INT);
func4(&e, FLT);
func4(&f, DBL);
如果指针指向特定数据类型,编译器如何知道(翻译)该特定数据类型的所有属性(大小,...,其他是什么?)?
如果我有例如:
char* foo[] = {"abc", "123", "def"};
,那么编译器必须创建双指针(指向指针的指针)才能拥有这个(地址)数组(字符)数组。
但为什么不是数据类型 void*
(因为它是寻址 - 地址数据类型是空的 - 到字符串),而不是数据类型 char
?
按照我现在的理解——无论它必须取消引用多少个地址(char**、char***、...),声明的数据类型都是针对最终找到的 VALUE。所以我将其理解为路径中的 'backstop',通过检查 最终值 大小找到实际值。因此,一旦编译器取消引用所有引用 - 它创建的路径 - 然后它只知道它找到了值,因为它是一个字节长并且以空字符终止 - 就像 char 一样(而不是继续取消引用一个地址,它是 8 个字节长)。
所以问题是,编译器如何知道特定的数据类型。 属性 编译器决定它是什么以及它有多长。它对其他事情做出决定吗?还是我的观念正确?
PS: 本例中不需要指针运算。
(as it is addressing -address datatype is void - to string)
foo
是指向字符的指针数组。 (不是双指针)
foo
中的元素是指向字符的指针(写作char*
)。那是数组中元素的类型。数组中的元素不是void*
,而是char*
。所以数组中元素的类型写成char*
.
char*
表示 "pointer to char
" 但 char*
本身 也是 一个完全有效的数据类型。它与 void*
不同。您可以有指向 char*
(写作 char**
)的指针,char*
的数组,等等。
...那么编译器必须制作双指针(指向指针的指针).
编译器 必须 在这种情况下创建一个 char ** 是不正确的。编译器将简单地将 char* foo[] = {"abc", "123", "def"};
视为一个由 3 个指针组成的数组,并使用字符串文字进行初始化。
但是,是正确的是,如果将同一个变量作为函数参数传递,则只有每个数组的第一个元素的地址会有效传递,从而导致您指向指针断言的指针。可以将此变量作为参数传递的函数原型包括:
void func2(char *a[]);
void func2(char *a[3]);
void func3(char **a, int order);//includes size information
因此给定 foo
如上定义,将按如下方式进行调用:
func2(foo);
func3(foo, 3);// requires size information
foo
的两个实例在被调用函数处理时都将被视为 char **
。
但为什么不是数据类型 void*...
简而言之,void *
是一种在程序员方面允许 type
歧义的方法。反之,如果使用得当,编译时就不会出现歧义。 (如果有,好的编译器会发出警告或错误。)。
在 C 中,关键字 void
的使用受到限制:
作为函数使用时return类型,表示函数 没有 return 值。
当它出现在指针声明中时,它指定 指针是通用的。
在函数的参数列表中使用时,void 表示 函数不带参数。
使用列表不包括创建非指针变量,如
void variable = s;// Illegal, creates a compile-time error.
但是,void *
对于处理可能作为函数参数传递的各种数据类型很有用。例如,给定:
typedef union {
int a;
char b;
float c;
double d;
} TYP;
TYP typ;
enum {
INT,
CHAR,
FLT,
DBL
}
void func4(void *a, int type)// void * provides type ambiguity in argument 1
{ //i.e. programmer can pass int, char or double
switch(type) {
case 0://int
typ.a = (int)a;
break;
case 1://char
typ.b = (char)a;
break;
case 2://float
typ.c = *(float *)(a);
break;
case 3://double
typ.d = *(double *)(a);
break;
};
}
附调用示例:
char c = 'P';
int d = 1024;
float e = 14.5;
double f = 0.0000012341;
func4(&c, CHAR);
func4(&d, INT);
func4(&e, FLT);
func4(&f, DBL);