函数原型和块代码中的变量声明:有区别吗?

时间:2019-01-07 11:11:01

标签: c arrays function-call

为什么weak_ptr<>在main而不是在函数原型中引发编译错误? 是否应该总是在函数原型中编写string[] guids = pguid.Split(','); string sqlin = ""; int paramno = -1; foreach (var guid in guids) { parametercount ++; sqlin = sqlin + "@Param" + (string)parametercount; + "," } dbCmd3.CommandText = "SELECT * FROM tbIndex where pguid in (" + sqlin.Substring(0, sqlin.Length-1) + ")"; for(int i = 0; i <= parametercount; i++){ dbCmd3.Parameters.Add("@Param" + (string)i, OleDbType.VarChar).Value = guids[i].Replace("'", ""); } 更好?

int array[]

3 个答案:

答案 0 :(得分:4)

在您的代码中的函数内部,为数组定义编写int array[];是语义错误。

在这种情况下,array是没有链接的变量,(“块作用域 声明的没有存储类说明符extern)的对象的标识符,并按照规范:

  

如果声明的对象标识符没有链接,则对象的类型应为   在其声明符[....]

的末尾完成

空的[](中间有空格或无空格)不能为数组定义建立有效的构造,因为数组的大小仍然未知(请注意,缺少显式花括号-随附的初始化程序列表)。因此,您的编译器会抱怨,因为类型不完整,并且不知道要为该数组变量保留的内存总量。

另一方面,对于函数参数,数组类型参数实际上会衰减为指向该类型的指针,因此,指定数组大小不是强制性的。引用第6.7.6.3节

  

将参数声明为“类型数组”应调整为“   类型”,其中类型限定词(如果有的话)是在[   数组类型派生。 [...]

  

如果函数声明符不是该函数定义的一部分,则参数可能具有   类型不完整,可以在其声明符说明符的序列中使用[*]表示法   指定可变长度数组类型。

因此,基本上,是一个声明

 void myfoo (int array[])

等同于

void myfoo (int *array)

所以,编译器会接受。

答案 1 :(得分:2)

从根本上说,main的块内的数组声明需要一个大小而函数参数中的数组声明不需要大小的原因是main中的声明是定义数组,而function参数仅仅是接收其他定义的数组。

因此main中的定义需要一个大小,因为它必须为数组保留存储空间。

function参数只是接收一个数组,因此只需要知道数组从哪里开始。它不需要知道大小。 (也就是说,编译器不需要知道大小即可编译代码。函数可能需要知道大小即可执行其预期目的,但这对程序员而言是问题,而不是编译器。)

由于使用C规则,因此数组实际上不能作为函数参数传递。只要将数组作为函数参数给出,编译器就会自动将其转换为指向其第一个元素的指针。同样,函数参数可以是指针,但实际上不能是数组。当您将函数参数声明为数组时,编译器会自动对其进行调整以声明一个指针。因此,函数声明void myfoo(int array[])会自动调整为void myfoo(int *array)

要求main中的声明具有大小的特定规则是C 2018 6.7 7:

  

如果声明的对象标识符没有链接,则该对象的类型应在其声明器的末尾或如果它具有初始化程序的情况在其init-declarator的末尾完成;…

答案 2 :(得分:1)

void myfoo (int array[]) { // No compilation error
;}

这意味着myfoo()将使用整数数组(任意大小)进行调用。编译器可以编译它。

void myfoo1 (int *array1) { // No compilation error
;}

这意味着myfoo1()将被指向整数的指针调用。编译器可以编译它。

int main() {
    int array[]; // Compilation error
    int* array1; // No compilation error
}

int array[];

这是数组的定义。但是编译器无法确定数组的大小。因此它不知道要分配多少内存。 因此,您必须提供size或使用以下一些值对其进行初始化。

int array[3];

int array[] = {1,2,1};

int* array1;

这只是整数指针的声明。没错,编译器可以编译它。