简体   繁体   English

是否保证类型T [x] [y]与C中的T [x * y]具有相同的内存布局?

[英]Is it guaranteed that the type T[x][y] has the same memory layout as T[x*y] in C?

So far thought it is, but after I learned that the compiler may pad data to align it for architecture requirements for example I'm in doubt. 到目前为止,我认为是这样,但是在得知编译器可以填充数据以使其符合体系结构要求之后,例如,我对此表示怀疑。 So I wonder if a char[4][3] has the same memory layout as char[12] . 所以我想知道char[4][3]是否具有与char[12]相同的内存布局。 Can the compiler put padding after the char[3] part to make it aligned so the whole array takes actually 16 bytes? 编译器是否可以在char[3]部分之后放置填充以使其对齐,以便整个数组实际占用16个字节?

The background story that a function of a library takes a bunch of fixed length strings in a char* parameter so it expects a continuous buffer without paddig, and the string length can be odd. 一个背景,一个库的函数在char*参数中使用了一堆固定长度的字符串,因此它期望没有paddig的连续缓冲区,并且字符串长度可以是奇数。 So I thought I declare a char[N_STRINGS][STRING_LENGTH] array, then conveniently populate it and pass it to the function by casting it to char* . 所以我以为我声明了一个char[N_STRINGS][STRING_LENGTH]数组,然后方便地对其进行填充,并通过将其强制转换为char*将其传递给函数。 So far it seems to work. 到目前为止,它似乎有效。 But I'm not sure if this solution is portable. 但我不确定该解决方案是否可移植。

An array of M elements of type A has all its elements in contiguous positions in memory, without padding bytes at all. 一个类型为M的M个元素的数组将其所有元素放在内存中的连续位置,完全不填充字节。 This fact is not depending on the nature of A. 此事实不取决于A的性质。

Now, if A is the type "array of N elements having type T", then each element in the T-type array will have, again, N contiguous positions in memory. 现在,如果A是类型“具有类型T的N个元素的数组”,则T类型数组中的每个元素在内存中将再次具有N个连续位置。 All these blocks of N objects of type T are, also, stored in contiguous positions. 所有这些类型为T的N个对象的所有块也都存储在相邻位置。

So, the result, is the existence in memory of M*N elements of type T, stored in contiguous positions. 因此,结果是在内存中存在类型T的M * N个元素,并存储在相邻位置。

The element [i][j] of the array is stored in the position i*N+j . 数组的元素[i][j]存储在位置i*N+j

Let's consider 考虑一下

T array[size]; 
array[0]; // 1

1 is formally defined as: 1的正式定义为:

The definition of the subscript operator [] is that E1[E2] is identical to (*((E1)+(E2))) 下标运算符[]的定义是E1[E2](*((E1)+(E2)))

per §6.5.2.1, clause 2 taken from the standard C draft N1570. 根据第6.5.2.1节第2条的规定,摘自标准C草案N1570。 When applied to multi-dimensional arrays, «array whose elements are arrays», we have: 当应用于多维数组«元素为数组的数组»时,我们有:

If E is an n-dimensional array (n ≥ 2) with dimensions i × j × ... × k , then E (used as other than an lvalue) is converted to a pointer to an (n − 1)-dimensional array with dimensions j × . . . × k. 如果E是维数为i × j × ... × k的n维数组(n≥2),则E(用作左值)将转换为指向(n − 1)维数组的指针尺寸为j × . . . × k. j × . . . × k.

Therefore, given E = T array[i][j] and S = array[i][j] , S is first converted to a pointer to a one-dimensional array of size j , namely T (*ptr)[j] = &array[i] . 因此,给定E = T array[i][j]S = array[i][j] ,首先将S转换为指向大小为j的一维数组的指针,即T (*ptr)[j] = &array[i]

If the unary * operator is applied to this pointer explicitly, or implicitly as a result of subscripting , the result is the referenced (n − 1)-dimensional array , which itself is converted into a pointer if used as other than an lvalue. 如果将一元*运算符显式或间接地应用于下标 ,则结果是被引用的(n-1)维数组 ,如果用作左值以外的数组 ,则其本身将转换为指针。

and this rule applies recursively. 这条规则是递归的 We may conclude that, in order to do so, the n-dimensional array must be allocated contiguously. 我们可以得出结论,为此,必须连续分配n-dimensional数组。

It follows from this that arrays are stored in row-major order (last subscript varies fastest). 由此可见,数组以行优先顺序存储(最后一个下标变化最快)。

in terms of logical layout. 就逻辑布局而言。

Since char [12] has to be stored contiguously and so has to char [3][4] , and since they have the same alignment, they should be compatible, despite they're technically different types. 由于char [12]必须连续存储,而char [3][4] char [12]也必须连续存储,并且由于它们具有相同的对齐方式,因此尽管它们在技术上是不同的类型,但它们应该兼容。

What you're referring to as types are not types. 您所说的类型不是类型。 The type T you mention in the title would be (in this case) a pointer to a char. 您在标题中提到的T类型(在这种情况下)将是指向char的指针。

You're correct that when it comes to structs, alignment is a factor that can lead to padding being added, which may mean that your struct takes up more bytes than meets the eye. 您是对的,对结构而言,对齐是导致填充增加的一个因素,这可能意味着您的结构占用的字节多于实际需要的字节。

Having said that, when you allocate an array, the array will be contiguous in memory. 话虽如此,当您分配一个数组时,该数组在内存中将是连续的。 Remember that when you index into an array, array[3] is equivalent to *(array + 3) . 请记住,当您索引到数组时, array[3]等效于*(array + 3)

For example, the following program should print out 12 : 例如,以下程序应打印出12

#include <stdio.h>

int main() {
    char array[4][3];
    printf("%zu", sizeof(array));
    return 0;
}

Strictly speaking a 2-D array is an array of pointers to 1-D arrays. 严格来说,二维数组是指向一维数组的指针的数组。 In general you cannot assume more than that. 通常,您不能承担更多的责任。

I would take the view that if you want a contiguous block of of any type then declare a contiguous 1D block, rather than hoping for any particular layout from the compiler or runtime. 我认为,如果您想要任何类型的连续块,请声明一个连续的1D块,而不是希望从编译器或运行时中获得任何特定的布局。

Now a compiler probably will allocate a contiguous block for a 2-D array when it knows in advance the dimensions ( ie they're constant at compile time ), but it's not the strict interpretation. 现在,如果编译器事先知道尺寸(即它们在编译时是恒定的),则可能会为2D数组分配一个连续的块,但这不是严格的解释。

Remember int main( int argc, char **argv ) ; 记住int main( int argc, char **argv ) ;

That char **argv is an array of pointers to char pointers. char **argv是指向char指针的指针的数组。

In more general programming you can eg malloc() each row in a 2D array separately and swapping row is as simple as swapping the values to those pointers. 在更通用的编程中,您可以例如在2D数组中分别malloc()每行,并且交换行就像将值交换到那些指针一样简单。 For example : 例如 :

char **array = NULL ;

array = malloc( 2 * sizeof( char * ) ) ;

array[0] = malloc( 24 ) ;

array[1] = malloc( 11 ) ;

strcpy( array[0], "first" ) ;
strcpy( array[1], "second" ) ;

printf( "%s\n%s\n", array[0], array[1] ) ;

/* swap the rows */

char *t = array[0] ;
array[0] = array[1] ;
array[1] = t ;

printf( "%s\n%s\n", array[0], array[1] ) ;

free( array[0] ) ;
free( array[1] ) ;
free( array ) ;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM