用c语言中的指针进行寻址

  • 本文关键字:寻址 指针 语言 c
  • 更新时间 :
  • 英文 :


我正在用Ted Jensen的"关于C〃中的指针和数组的一个定理;手册这是一个非常棘手的争论。

问题1。我已经来到了程序3.1,希望得到澄清。这就是程序:

#include <stdio.h> 
char strA[80] = "A string to be used for demonstration purposes";
char strB[80]; 
int main(void) { 
char *pA; 
char *pB;
puts(strA); 
pA = strA; 
puts(pA); 
pB = strB;
putchar('n');
while(*pA != '')
{ 
*pB++ = *pA++; 
} 
*pB = '';
puts(strB);
return 0; 
}

关于线pA = strA;;然后我们将指针pA指向strA。即通过赋值语句将strA[0]的地址复制到我们的变量pA〃中;,这是我不明白的。

要通过赋值声明将strA[0]的地址复制到我们的变量pA中,我们不应该写pA = & strA吗?

问题2。表达式c = * ++ p;增加了p的值或p的地址?

间接运算符(*)是否不指示指向变量的值?

要通过赋值声明将strA[0]的地址复制到我们的变量pA中,我们不应该写pA = & strA吗?

&strAstrA的地址。CCD_ 11是CCD_ 12的地址。它们是"相同的",因为它们指向内存中的同一位置,但它们有不同的类型,如果我们在pA的类型是指向strA元素类型的指针时编写pA = &strA,编译器会抱怨。

当我们写入pA = strA时,数组strA会自动转换为指向其第一个元素的指针,因此pA = strA等效于pA = &strA[0]

问题2:表达式c = * ++ p;会增加p的值还是p的地址?

C语法将其组织为c = *(++p);,而++p增加了p的值。如果p是一个指针,它会增加该指针的值。*运算符使用增加的值。

谈到指针的地址时要小心。指针的值是一个地址,但不应该说这是指针的地址。指针本身就是内存中的一个对象,因此它在内存中有一个存储其值的地址。存储指针的地址与存储在其中的地址不同。"指针的地址"是存储指针的位置,而不是指针的值。

这只是因为strA是一个指针,它是char数组。一个数组的";值";实际上只不过是数组的第一个元素的地址。

当您分配基元数据类型(int、char等)的地址时,应该按照您描述的方式进行分配。

int x;
int *pA;
pA = &x;

当您分配指针数据类型(数组等)的地址时,您应该在不带&运算符,因为值本身就是地址。

int x[10];
int* pA;
pA = x;

原始代码

#include <stdio.h>
char strA[80] = "A string to be used for demonstration purposes";
char strB[80];
int main(void)
{
char *pA; /* a pointer to type character */
char *pB; /* another pointer to type character */
puts(strA); /* show string A */
pA = strA; /* point pA at string A */
puts(pA); /* show what pA is pointing to */
pB = strB; /* point pB at string B */
putchar('n'); /* move down one line on the screen */
while(*pA != '') /* line A (see text) */
{
*pB++ = *pA++; /* line B (see text) */
}
*pB = ''; /* line C (see text) */
puts(strB); /* show strB on screen */
return 0;
}

在C中,当您编写:时

char strA[80];

内存已分配给您的表。这是一个例子,你可以尝试将它想象成什么样子。

<1]2nd元素>>n
[0]第一个元素[2]3rd元素[….]…第n个元素
0000000100020003

要通过赋值声明将strA[0]的地址复制到我们的变量pA中,我们不应该写pA=&strA?

数组很奇怪,行为与其他类型不同。

表达式CCD_;衰变";从类型";CCD_ 27〃的N元素阵列;至";指向CCD_ 28的指针";,并且表达式的值是第一个元素的地址。这个";衰变;当数组表达式是sizeof或一元&运算符的操作数时不会发生,因此表达式&strA具有类型";指向CCD_ 32的N元素阵列的指针";,或者与char *不同的char (*)[N]。地址值相同(数组的地址与其第一个元素的地址相同),但类型不同。

假设声明

char str[N]; // for some size N
char *p;

当你写

p = str; // char * = char *

表达式CCD_ 35具有类型";CCD_ 36〃的N元素阵列;;然而,由于str不是sizeof或一元&运算符的操作数;衰变";以键入CCD_ 40并计算为第一个元素的地址。这相当于写

p = &str[0];  // char * = char *

这是有原因的——C源于早期的一种名为B的语言,在B中,数组类型有一个指向第一个元素的专用指针——当你在B中声明一个类似的数组时

auto a[N];

你记忆中的是

+---+
a: |   | -------+
+---+        |   
...         |
+---+        |
|   | a[0] <-+
+---+
|   | a[1]
+---+
...

并且数组下标运算a[i]定义为*(a + i)-给定起始地址a,从该地址偏移i元素并取消引用结果。

在设计C时,Ritchie希望保留B的数组行为,但他不希望保留该行为所需的显式指针。当你在类似的C中声明一个数组时

int a[N];

你在记忆中得到的是

+---+
a: |   | a[0]
+---+  
|   | a[1]
+---+
...

编译器不是为指向第一个元素的显式指针留出空间,而是用指向a[0]的指针替换表达式a的任何出现。所以a[i]仍然被定义为*(a + i)。不幸的是,这意味着数组失去了它们的";阵列度";在大多数情况下,大多数时候,你所处理的都是一个指针。

问题2:表达式c=*++p;增加p的值或p的地址?

这有点复杂。要按要求回答,它会增加p——它会将p设置为指向序列中的下一个对象。这可能可以用一个具体的例子来更好地解释。

假设以下声明:

char str[] = "foo";
char *p = str;

则以下情况成立:

+---+
str: |'f'| str[0]   <--- p
+---+
|'o'| str[1]   <--- p + 1
+---+
|'o'| str[2]   <--- p + 2
+---+
| 0 | str[3]   <--- p + 3
+---+
p == &str[0]             // char * == char *
*p ==  str[0] == 'f'      // char   == char   == char
p + 1  == &str[1]
*(p + 1) ==  str[1] == 'o'
p + 2  == &str[2]
*(p + 2) ==  str[2] == 'o'

表达式p + 1的结果是指向str[1]的指针,表达式p + 2的结果是针对str[2]的指针,等等。

c = *++p;大致相当于写入

tmp = p + 1;
c = *tmp;
p = p + 1;

需要注意的是,对cp的更新可以以任何顺序发生——它们甚至可以同时评估(交错或并行)。

在这种情况下,这意味着我们将*(p + 1)('o')的值分配给c,并将p更新为指向str[1],剩下的是:

+---+
str: |'f'| str[0]   
+---+
|'o'| str[1]   <--- p
+---+
|'o'| str[2]   <--- p + 1
+---+
| 0 | str[3]   <--- p + 2
+---+
p == &str[1]
*p ==  str[1] == 'o'
p + 1  == &str[2]
*(p + 1) ==  str[2] == 'o'
p + 2  == &str[3]
*(p + 2) ==  str[3] == 0

最新更新