Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/68.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/kotlin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C语言中的数组长度_C_Arrays_Function_Parameters_C99 - Fatal编程技术网

C语言中的数组长度

C语言中的数组长度,c,arrays,function,parameters,c99,C,Arrays,Function,Parameters,C99,我以前是一名C程序员,对于C语言有一些我无法理解的地方,我正在使用C99标准进行编码 有人告诉我,在C语言中,没有办法知道数组的长度,我需要将其长度作为参数发送给我愿意使用的函数,但为什么呢? 例如,在C语言中,我们可以键入array_name.lenght 另外,在二维数组中,为什么必须指定数组的列数?我的意思是为什么这样做: void test1 (int arr[][m]) { } 但这并不是: void test2 (int arr[][]) { } 在C语言中,作为参数传递给函数的

我以前是一名C程序员,对于C语言有一些我无法理解的地方,我正在使用C99标准进行编码


有人告诉我,在C语言中,没有办法知道数组的长度,我需要将其长度作为参数发送给我愿意使用的函数,但为什么呢? 例如,在C语言中,我们可以键入array_name.lenght

另外,在二维数组中,为什么必须指定数组的列数?我的意思是为什么这样做:

void test1 (int arr[][m])
{
}
但这并不是:

void test2 (int arr[][])
{
}

在C语言中,作为参数传递给函数的数组被转换为指向数组第一个元素的指针。数组的大小不会隐式传递给函数。程序员负责将正确的数组大小传递给函数

int sum(int *num, size_t length)
{
   int total = 0;
   int i;
   for (i = 0; i < length; i++)
   {
      total += num[i];
   }
}

这种方法的一个问题是,假定数组的参数只指向数组。它可以指向任何int,不管该int是否是数组的元素。如果犯了这个错误,就会发生典型的缓冲区溢出。

在C语言中,作为参数传递给函数的数组将转换为指向数组第一个元素的指针。数组的大小不会隐式传递给函数。程序员负责将正确的数组大小传递给函数

int sum(int *num, size_t length)
{
   int total = 0;
   int i;
   for (i = 0; i < length; i++)
   {
      total += num[i];
   }
}

这种方法的一个问题是,假定数组的参数只指向数组。它可以指向任何int,不管该int是否是数组的元素。如果犯了这个错误,就会发生典型的缓冲区溢出。

C是一种过程语言,比大多数过程语言更接近汇编语言,而不是面向对象的语言。Algol和C比Smalltalk和C来得早,Smalltalk给了我们一些重要的教训

有时,您可以在C中使用以下命令:

#define num_elements(array) (sizeof(array) / sizeof(array[0]))
…但当数组被传递给函数时,通常不再有效

另一个在C中几乎任何情况下都适用的好方法是:

#define MY_ARRAY_ELEMENTS 1000
int a[MY_ARRAY_ELEMENTS];
foo(a, MY_ARRAY_ELEMENTS);
下面,为特定数组的长度定义一个符号常量,并使用它代替硬编码常量

OO语言有与对象关联的元数据,那么为什么不在元数据中存储长度呢?然而,C并没有做这种事情——它是在字节非常宝贵的时候创建的,元数据被认为开销太大

为什么要部分定义n维数组的大小?因为在幕后,C正在做一些数学运算,将[x][y]存在于内存中的位置相乘,而且它也没有存储元数据来帮助您跟踪这些维度


假设另一种过程语言Pascal使数组维度成为数组类型的一部分。这是一种相反的极端-大小和形状在类型系统中保持跟踪,但实际上在实践中使用非常严格。因此,编写一个函数来求两个不同长度的两个不同数组中的浮点数之和是不切实际的。

C是一种过程语言,比大多数过程语言更接近汇编语言,而不是面向对象的语言。Algol和C比Smalltalk和C来得早,Smalltalk给了我们一些重要的教训

有时,您可以在C中使用以下命令:

#define num_elements(array) (sizeof(array) / sizeof(array[0]))
…但当数组被传递给函数时,通常不再有效

另一个在C中几乎任何情况下都适用的好方法是:

#define MY_ARRAY_ELEMENTS 1000
int a[MY_ARRAY_ELEMENTS];
foo(a, MY_ARRAY_ELEMENTS);
下面,为特定数组的长度定义一个符号常量,并使用它代替硬编码常量

OO语言有与对象关联的元数据,那么为什么不在元数据中存储长度呢?然而,C并没有做这种事情——它是在字节非常宝贵的时候创建的,元数据被认为开销太大

为什么要部分定义n维数组的大小?因为在幕后,C正在做一些数学运算,将[x][y]存在于内存中的位置相乘,而且它也没有存储元数据来帮助您跟踪这些维度


假设另一种过程语言Pascal使数组维度成为数组类型的一部分。这是一种相反的极端-大小和形状在类型系统中保持跟踪,但实际上在实践中使用非常严格。因此,编写一个函数将两个不同长度的两个不同数组中的浮点数相加是不切实际的。

在大多数编程语言中,数据类型都是抽象的:也就是说,如果你要一个数字列表,它会在内存中创建结构来存储一个数字列表,并跟踪其容量、有多少元素已满,可能还有元素是null还是包含值等等

C是一种不处理抽象的低级语言;它直接处理物理内存。如果您请求空间来放置5个整数,它会为5个整数分配内存。你想让它跟踪数字5所以
我记得你在哪里分配了5个整数?在大多数编程语言中,数据类型都是抽象的:也就是说,如果你要一个数字列表,它会在内存中创建结构来存储一个数字列表,并跟踪其容量、有多少元素已满,可能还有元素是null还是包含值等等

C是一种不处理抽象的低级语言;它直接处理物理内存。如果您请求空间来放置5个整数,它会为5个整数分配内存。您想让它在某个地方跟踪数字5,以记住您分配了5个整数?你不是自找的,你得自己做

例如,在C语言中,我们可以键入array_name.length

我不使用C,但是,如果在子例程中可以获得在别处创建的数组的长度,那么关于该长度的信息必须存储在内存中,并与数组一起传递。必须将该长度放入内存中,并且,当数组作为参数传递时,必须包含不仅仅是数组长度的信息。所以C使用内存和计算时间

这样做的结果是,您无法直接控制计算机。只要有东西在传递额外的信息,就无法编写更简单、更高效的程序。这必然是浪费。只要您在资源充足的情况下编写程序,这是很好的

C不做额外的努力。当传递数组时,只传递其位置,这就是访问其元素所需的全部内容。如果某个特定的子例程需要它的长度,您可以手动传递它,这是您在需要时的选择,但您也可以选择在不需要资源时不浪费资源。你可以编写更高效的程序

在二维数组中,为什么必须指定数组的列数

如果我们知道arr是int的数组,那么我们就知道元素arr[0]在开头,arr[1]在后面,arr[2]在后面,依此类推。要使用一维数组,我们只需要知道它从哪里开始

如果我们知道数组是一个int的二维数组,我们知道[0][0]在开头,arr[0][1]在后面,依此类推,但我们不知道arr[1][0]在哪里。它是在一定数量的元素arr[0][i]之后,但我们不知道有多少元素,除非我们知道第二维度。因此,为了使用二维数组,必须知道第二个维度的长度。这是合乎逻辑的要求,而不是选择

补充 通常,例程只需要知道它应该使用数组的哪些元素。它不需要知道数组中有多少个元素

例程不需要给定数组长度的情况包括:

要计算缓冲区中字符串的长度,类似strlen的例程只需检查缓冲区中的每个字节,直到找到空字节。它不需要知道整个缓冲区有多大。示例:一个程序创建一个100字节的缓冲区。它从终端读取字节,直到找到新行。用户仅键入12个字符,然后键入新行。缓冲区由12个字节和一个空字符填充。检查字符串的子例程只需要使用13个字节,而不是100个字节。 一个例程可以处理固定数量的元素。例如,用于帮助进行数值积分的子例程可能一次获取三个函数值,将曲线拟合到它们,然后返回曲线下的面积。主例程可能有一个完整的函数值数组,它反复调用子例程以计算数组中的不同点,并向子例程传递指向要处理位置的指针。在每次调用中,子例程只需要知道在给定地址有三个值。它不需要知道完整阵列中有多少个。 一个例程可以处理多个数组中相同数量的元素。例如,执行离散傅里叶变换的例程可能需要处理多个元素N和四个数组:一个用于输入实部,一个用于输入虚部,一个用于输出实部,一个用于输出虚部。对于每个数组,例程使用N个元素。这个数字N只需要在一个参数中传递给例程。将其存储在多个位置(每个阵列一个位置)会造成浪费。 另一个需要考虑的问题是,有时我们只将数组的一部分传递给例程。如果缓冲区中有某个字符串,我可能希望子例程只处理该字符串的一部分,可能只处理已解析的命令中的一个字。要做到这一点,我可以只传递一个指向该单词开头和要处理的单词长度的指针。在这种情况下,子例程不仅不需要知道数组的长度 ,它甚至不需要知道数组的起始位置。它只需要知道它被要求做什么。传递任何其他信息都是浪费

例如,在C语言中,我们可以键入array_name.length

我不使用C,但是,如果在子例程中可以获得在别处创建的数组的长度,那么关于该长度的信息必须存储在内存中,并与数组一起传递。必须将该长度放入内存中,并且,当数组作为参数传递时,必须包含不仅仅是数组长度的信息。所以C使用内存和计算时间

这样做的结果是,您无法直接控制计算机。只要有东西在传递额外的信息,就无法编写更简单、更高效的程序。这必然是浪费。只要您在资源充足的情况下编写程序,这是很好的

C不做额外的努力。当传递数组时,只传递其位置,这就是访问其元素所需的全部内容。如果某个特定的子例程需要它的长度,您可以手动传递它,这是您在需要时的选择,但您也可以选择在不需要资源时不浪费资源。你可以编写更高效的程序

在二维数组中,为什么必须指定数组的列数

如果我们知道arr是int的数组,那么我们就知道元素arr[0]在开头,arr[1]在后面,arr[2]在后面,依此类推。要使用一维数组,我们只需要知道它从哪里开始

如果我们知道数组是一个int的二维数组,我们知道[0][0]在开头,arr[0][1]在后面,依此类推,但我们不知道arr[1][0]在哪里。它是在一定数量的元素arr[0][i]之后,但我们不知道有多少元素,除非我们知道第二维度。因此,为了使用二维数组,必须知道第二个维度的长度。这是合乎逻辑的要求,而不是选择

补充 通常,例程只需要知道它应该使用数组的哪些元素。它不需要知道数组中有多少个元素

例程不需要给定数组长度的情况包括:

要计算缓冲区中字符串的长度,类似strlen的例程只需检查缓冲区中的每个字节,直到找到空字节。它不需要知道整个缓冲区有多大。示例:一个程序创建一个100字节的缓冲区。它从终端读取字节,直到找到新行。用户仅键入12个字符,然后键入新行。缓冲区由12个字节和一个空字符填充。检查字符串的子例程只需要使用13个字节,而不是100个字节。 一个例程可以处理固定数量的元素。例如,用于帮助进行数值积分的子例程可能一次获取三个函数值,将曲线拟合到它们,然后返回曲线下的面积。主例程可能有一个完整的函数值数组,它反复调用子例程以计算数组中的不同点,并向子例程传递指向要处理位置的指针。在每次调用中,子例程只需要知道在给定地址有三个值。它不需要知道完整阵列中有多少个。 一个例程可以处理多个数组中相同数量的元素。例如,执行离散傅里叶变换的例程可能需要处理多个元素N和四个数组:一个用于输入实部,一个用于输入虚部,一个用于输出实部,一个用于输出虚部。对于每个数组,例程使用N个元素。这个数字N只需要在一个参数中传递给例程。将其存储在多个位置(每个阵列一个位置)会造成浪费。
另一个需要考虑的问题是,有时我们只将数组的一部分传递给例程。如果缓冲区中有某个字符串,我可能希望子例程只处理该字符串的一部分,可能只处理已解析的命令中的一个字。要做到这一点,我可以只传递一个指向该单词开头和要处理的单词长度的指针。在这种情况下,子例程不仅不需要知道数组的长度,甚至不需要知道数组的起始位置。它只需要知道它被要求做什么。传递任何其他信息都是浪费。

我需要将其长度作为参数发送给我愿意使用的函数,但这是为什么?因为语言不支持另一种方式。这实际上是一个很好的问题——他问的是运行时环境的差异和历史视角,这比大多数人对语言的思考要深刻得多。他不仅仅是说为什么C很臭?你当然可以确定数组的长度:sizeof array/si

数组[0]的数目。问题是C不允许数组作为函数参数,而且看起来像数组类型的参数实际上是指针类型的。强烈建议阅读:的第6节。我需要将其长度作为参数发送给我愿意使用的函数,但为什么?因为语言不支持另一种方式。这实际上是一个很好的问题——他问的是运行时环境的差异和历史视角,这比大多数人对语言的思考要深刻得多。他不仅仅是在说为什么C很臭?你当然可以确定数组的长度:sizeof array/sizeof array[0]。问题是C不允许数组作为函数参数,而且看起来像数组类型的参数实际上是指针类型的。强烈建议阅读:的第6节。但是,如果它只知道列的数量而不知道行的数量,它怎么知道[x][y]存在的位置呢?在除最后一个维度外的所有维度中,都需要乘以该轴上的值的数量。最后一个值不是大小,而是偏移量只是相加,而不是相乘。考虑一个+x*NUMYStudio+Y。除非启用了边界检查,否则num_rows不必出现在等式中。但如果它只知道列数而不知道行数,它怎么知道[x][y]存在的位置呢?在除最后一个维度外的所有维度中,都需要乘以该轴上的值数。最后一个值不是大小,而是偏移量只是相加,而不是相乘。考虑一个+x*NUMYStudio+Y。除非你打开了边界检查,否则num_行不需要进入等式。里奇的语言处理物理内存。clang和gcc优化器处理的语言要求程序员将内存的使用限制在与优化器的Abstration匹配的范围内,并且如果程序需要执行那些抽象所不能满足的操作,则不会可靠地运行。里奇的语言处理物理内存。clang和gcc优化器处理的语言要求程序员将内存的使用限制在与优化器的限制相匹配的范围内,如果程序需要做那些抽象所不能满足的事情,那么它就不能可靠地运行。另外两个问题:您提到了,但是您也可以选择在不需要资源时不浪费资源。你可以编写更高效的程序。但是,在不知道数组的尺寸的情况下,我如何需要并使用它呢?你能举个例子吗?此外,我认为这并不是一项繁重的任务,因为我们所节省的只是一小部分。我们真的需要这么高效吗?为什么?@Daniel98:使用它不需要知道数组的大小。您只需要知道应该使用多少元素和哪些元素。如果我要求一个子程序在指针中加三个元素,我把它放在一个数组的中间,它只需要知道它应该使用三个元素。不需要知道整个数组中有多少个元素。@Daniel98:是的,效率很重要。指针经常在程序中传递。我们制作链表,将文本读入缓冲区,解析文本并将指针传递给子程序,我们使用指针构造树和其他数据结构。使用图形窗口的例程具有指向窗口的指针和指向其中子结构的指针,例如关于按钮所在位置以及单击按钮时调用哪些例程的信息,指向其中文本的指针,等等。如果每一个指针都必须包含它所指向的东西的大小的信息,那么许多程序所使用的空间将大大增加。另外两个问题:你提到了,但你也可以选择在不需要资源时不浪费资源。你可以编写更高效的程序。但是,在不知道数组的尺寸的情况下,我如何需要并使用它呢?你能举个例子吗?此外,我认为这并不是一项繁重的任务,因为我们所节省的只是一小部分。我们真的需要这么高效吗?为什么?@Daniel98:使用它不需要知道数组的大小。您只需要知道应该使用多少元素和哪些元素。如果我要求一个子程序在指针中加三个元素,我把它放在一个数组的中间,它只需要知道它应该使用三个元素。不需要知道整个数组中有多少个元素。@Daniel98:是的,效率很重要。指针经常在程序中传递。我们制作链表,将文本读入缓冲区,解析文本并将指针传递给子程序,我们使用指针构造树和其他数据结构。使用图形窗口的例程具有指向窗口的指针和指向其中子结构的指针,例如关于按钮所在位置以及单击按钮时调用哪些例程的信息,指向其中文本的指针,等等。如果每个指针
必须包括它所指的东西的大小的信息,许多程序所使用的空间会增加相当多。