编译器如何处理数据类型?

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);