我写了以下程序。
#include<windows.h>
#include <stdio.h>
#include<tchar.h>
#define MAX_ARG 5
#define MAX_COMMAND_LINE 10
int _tmain(int argc, LPTSTR argv[]){
BOOL exitFlag = FALSE;
TCHAR command[MAX_COMMAND_LINE], *pc;
DWORD i, localArgc;
TCHAR argstr[MAX_ARG][MAX_COMMAND_LINE] = {"abcdef", "Dravid", "sachin", "ganguli" };
char name[10] = "Happy";
// Why argstr == argstr[0]
printf("%p %p \n", name, name[0] ); // name != name[0]
printf("%p %p = %p\n", argstr, argstr[0], *argstr);
// Why there is no difference if it increase left or right variable value?
TCHAR *place = malloc(10 * sizeof(TCHAR *));
place = argstr[0];
printf("%c %c \n", *++place, *place ); // Incremented the left parameter
printf("%c %c \n", *place, *++place ); // Incremented the right parameter
return 0;
}
1)为什么argstr==argstr[0]?
2)在printf中,从哪一侧(右/左)进行计算?
最佳答案
首先,根据您的声明,argstr
在内存中的布局如下:
+---+
argstr: |'a'| argstr[0][0]
+---+
|'b'| argstr[0][1]
+---+
|'c'| argstr[0][2]
+---+
...
+---+
|'f'| argstr[0][5]
+---+
| 0 | argstr[0][6]
+---+
...
+---+
| ? | argstr[0][9]
+---+
|'D'| argstr[1][0]
+---+
|'r'| argstr[1][1]
+---+
...
+---+
| ? | argstr[1][9]
+---+
|'s'| argstr[2][0]
+---+
...
+---+
| ? | argstr[4][9]
+---+
所有50个数组元素都按行主顺序顺序排列(即,第一行的所有元素,然后是第二行的所有元素,等等)。注意,没有为任何地方的指针预留存储空间。这意味着第一子阵列的第一个元素的地址(
&argstr[0][0]
)与数组的第一个元素的地址(&argstr[0]
)相同,后者与数组的地址(&argstr
)相同。除非它是
sizeof
或一元&
运算符的操作数,或是用于在声明中初始化另一个数组的字符串文字,否则“N-element array ofT
”类型的表达式将转换为“pointer toT
”类型的表达式(“decay”,表达式的值将是数组第一个元素的地址。在您的
printf
调用中,表达式argstr
具有类型“5-element array of 10 element array ofTCHAR
”。由于它不是sizeof
或一元&
运算符的操作数,因此它被转换为“指向TCHAR
”或TCHAR (*)[10]
的10元素数组的指针”类型的表达式,并且表达式的值是第一个元素(&argstr[0]
)的地址。在同一调用中,表达式
argstr[0]
具有类型“10 element array ofTCHAR
”。因为它不是sizeof
或一元&
运算符的操作数,所以它被转换为“pointer toTCHAR
”或TCHAR *
类型的表达式,并且表达式的值是第一个元素(&argstr[0][0]
)的地址。我勒个去?为什么数组表达式的类型会变成指针?
数组下标运算符
[]
是根据指针算法定义的:表达式a[i]
定义为*(a + i)
。给定一个地址a
,从该地址偏移i
元素(不是字节)并取消对结果的引用。这是从B语言派生的C语言的继承。在B中,作为数组定义的一部分创建了一个单独的指针;该指针将绑定到数组名称并指向数组的第一个元素,因此在B&argstr
和&argstr[0]
中确实会有所不同。里奇在设计C时去掉了数组指针,但他想保留B的数组语义,所以他创建了上面的数组转换规则。在类似于
argstr[i][j]
的表达式中,子表达式argstr
首先转换为指针值,该指针值用[i]
下标;这将为我们提供另一个数组表达式,该数组表达式转换为新的指针表达式,该指针表达式用[j]
下标。综上所述,考虑到声明
TCHAR argstr[5][10]
,以下所有内容都是正确的: Expression Type Decays to Value
---------- ---- --------- -----
argstr TCHAR [5][10] TCHAR (*)[10] Address of argstr[0]
&argstr TCHAR (*)[5][10] n/a Address of argstr
*argstr TCHAR [10] TCHAR * Value of argstr[0]
argstr[i] TCHAR [10] TCHAR * Address of argstr[i][0]
&argstr[i] TCHAR (*)[10] n/a Address of argstr[i]
*argstr[i] TCHAR n/a Value of argstr[i][0]
argstr[i][j] TCHAR n/a Value of argstr[i][j]
&argstr[i][j] TCHAR * n/a Address of argstr[i][j]
argstr
、&argstr
、*argstr
、argstr[0]
、&argstr[0]
和&argstr[0][0]
都产生相同的值(数组第一个元素的地址),但表达式的类型不同。