C语言之数组名的含义

一:一维数组 int a[5];

a:就是数组名。a做左值时表示整个数组的所有空间(10×4=40字节),又因为C语言规定数组操作时要独立单个操作,不能整体操作数组,所以a不能做左值;a做右值表示数组首元素(数组的第0个元素,也就是a[0])的首地址(首地址就是起始地址,就是4个字节中最开始第一个字节的地址)。a做右值等同于&a[0];

a[0]:表示数组的首元素,也就是数组的第0个元素。做左值时表示数组第0个元素对应的内存空间(连续4字节);做右值时表示数组第0个元素的值(也就是数组第0个元素对应的内存空间中存储的那个数)

&a:就是数组名a取地址,字面意思来看就应该是数组的地址。&a不能做左值(&a实质是一个常量,不是变量因此不能赋值,所以自然不能做左值。);&a做右值时表示整个数组的首地址。

&a[0]:字面意思就是数组第0个元素的首地址(搞清楚[]和&的优先级,[]的优先级要高于&,所以a先和[]结合再取地址)。做左值时表示数组首元素对应的内存空间,做右值时表示数组首元素的值(也就是数组首元素对应的内存空间中存储的那个数值)。做右值时&a[0]等同于a。

总结:

1:&a和a做右值时的区别:&a是整个数组的首地址,而a是数组首元素的首地址。

这两个在数字上是相等的,但是意义不相同。意义不相同会导致他们在参与运算的时候有不同的表现。

2:a和&a[0]做右值时意义和数值完全相同,完全可以互相替代。

3:&a是常量,不能做左值。

4:a做左值代表整个数组所有空间,所以a不能做左值。

#include<stdio.h>
int main (void)
{
    int a[5]={1,2,3,4,5};
    int *p1;
    int (*p2)[5];
    printf("p1 = %p \n",p1);
    printf("p2 = %p \n",p2);
    p1 = a;
    p2 = &a;
    printf("p1 = %p \n",p1);
    printf("(p1+1) = %p \n",(p1+1));
    printf("p2 = %p \n",p2);
    printf("(p2+1) = %p \n",(p2+1));
    return 0;
}

/******运行结果

p1 = 0xbfbcda54

p2 = 0xbfbcda5c

p1 = 0xbfbcd99c

(p1+1) = 0xbfbcd9a0

p2 = 0xbfbcd99c

(p2+1) = 0xbfbcd9b0

*******************/

/*********分析:*****

1:p1 p2定义的时候被没有进行初始化,所以属于野指针。

2:p1 = a ,a数组名做右值表示首元素首地址,而数组a是int类型,所以首元素首地址中存放的也是int类型的数所以类型匹配。也就是说p1是指向int类型的数的指针

3:p1+1=p1+4 p1指向的数组的首元素首地址,相当于p1指向了数组内部,所以p1+1其实就是p1+sizeof(数组类型)

4:p2 = &a p2的定义是int(*p2)[5]可以理解为是一个指向int [5]类型的指针,所以p2是一个指向数组的指针。

而&a是数组名取地址,表示的就是数组的地址(表示这个地址存放的就是一个数组类型),所以p2和&a的类型匹配。

5:p2 + 1 = p2 + 20   因为p2在定义的时候就被定义为指向一个int [5]类型的地址,所以

p2+1 = p2+sizeof(int [5]);

6:指针+1实际上就是指针+siezof(指针类型),这个其实是在定义的时候就已经确定了,因为在初始化的时候

指针指向的类型一定要和指针定义时候的类型匹配。

例如

char a[5];

int *p;        //p是一个指向int类型的指针

p = a ;则类型就不匹配,编译不通过。但是假如这样可以成功初始化,那么指针再运算的时候它的指向就会出错

比如开始p = a 的地址是0xb2000000,那么p+1 则为0xb2000004,而0xb2000004实际上是a[3]而不是a[1]这样就

无法进行运算了,所以指针类型的匹配主要是为了能够进行运算。

*******************************************/

二:二维数组

#include<stdio.h>
int main(void)
{
    int a[2][5];
    int *p1;
    int (*p2)[5];
    int b = 5;
    //p1 = a;  //编译报错,类型不匹配
    p2 = a;  //编译不报错,类型匹配
    printf("a = %p \n",a);
    printf("&a[0] = %p \n",&a[0]);
    printf("p2 = %p \n",p2);
    printf("p2 + 1 = %p \n", p2+1);  //这里进行p2 + 1,p2的值并不变
    printf("p2 = %p \n",p2);
    printf("*(p2 + 1)+1 = %p \n", *(p2 + 1)+1);
    return 0;
}

/**********运行结果************

a = 0xbfeaebc8

&a[0] = 0xbfeaebc8

p2 = 0xbfeaebc8

p2 + 1 = 0xbfeaebdc

*(p2 + 1)+1 = 0xbfeaebe0

**************************/

/************分析*****

1:p2是int* [5] 类型是一个指向int [5]的指针,

2:数组名做右值表示的是数组的首元素首地址,二维数组的数组名表示的是第一维的地址,类型也是int [5]

所以和p2的类型匹配

3:p2+1 = p2 +20 原因也就是p2指向的是int [][5],所以p2 + 1实际上+是指向了a[1][]也就是第一维的第二个元素。

4:*(p2 + 1)+1 =(p1+1)+4 ,指向是的a[1][1] 也就是说*(*(p+i)+j)等于a[i][j]。

*/

时间: 2024-12-24 16:07:57

C语言之数组名的含义的相关文章

C语言 对数组名取地址

作者 : 卿笃军 你有没有想过,对一个一维数组名取地址,然后用这个地址进行加减运算.这会出现什么样的结果呢? 示例: int a[5] = {1,2,3,4,5}; int *p = (int *)(&a+1); printf("%d\n",*(p-1)); 这个输出会是多少呢? 咦?为什么第二行需要强制转化类型呢? 答:a是一个一维数组的名字,&a相当于一个指向一维数组的指针.怎么感觉这么熟悉?指向数组的指针,那不就是行指针吗?int (*p)[]. 行指针+1,就是

对于C语言中数组名是指针的理解

我们都知道,c语言中数组名是一个指针,比如下面这段代码 #include<iostream>using namespace std;int main(){ int a[4]={1,2,3,4}; for(int i=0;i<4;i++) {  cout<<*(a+i);//*(a+i)和a[i]是等价的.  cout<<endl; } return 0;} 但是看下面这个代码 #include<iostream>using namespace std;

C语言--一维数组和多维数组数组名的含义

一.一维数组 对于一维数组,我们很容易理解数组名和元素地址的关系,即数组名代表数组首地址,亦即第一个元素的地址. 如定义数组int a[9]={1,2,3,4,5,6,7,8,9},则由上面的说明可得 a=&a[0],*a=a[0]: a+1=&a[1],*(a+1)=a[1]: ......... 二.二维数组 对于二维数组,我们一定要记住:它是数组的数组.如定义一个二维数组int b[3][4]={1,2,3,4,5,6,7,8,9,10,11,12},此时我们知道,可以把b看做是一个

C语言的数组名和对数组名取地址

http://blog.csdn.net/zdcsky123/article/details/6517811 相信不少的C语言初学者都知道,数组名相当于指针,指向数组的首地址,而函数名相当于函数指针,指向函数的入口地址.现在又这样一个问题,如果对数组名取地址,那得到的会是什么呢?很多人立刻会想到:给指针取地址,就是指针的指针,既二级指针嘛!当然这样的结论是错误的,不然这篇笔记也就没有意义了. 下面我们来逐步分析,下面是一段验证这个问题的代码 Code: #include<stdio.h> in

c语言中数组名的本质

c语言中的数组名的本质是什么,数组名是指针吗? 1.数组名是数组元素的首地址#include <stdlib.h>#include <stdio.h>void main() { int a[10] = {1, 2, 3, 4, 5, 6, 7, 8,9, 10}; printf("a:%d &a:%d :%d \n", a, &a); system("pause"); }上面的程序中,a &a大小一样,证明a就是数组元

C语言对数组名取地址

你有没有想过,对一个一维数组名取地址,然后用这个地址进行加减运算.这会出现什么样的结果呢? 示例: int a[5] = {1,2,3,4,5}; int *p = (int *)(&a+1); printf("%d\n",*(p-1)); 这个输出会是多少呢? 咦?为什么第二行需要强制转化类型呢? 答:a是一个一维数组的名字,&a相当于一个指向一维数组的指针.怎么感觉这么熟悉?指向数组的指针,那不就是行指针吗?int (*p)[]. 行指针+1,就是对指针进行加减操作

【C语言】数组名传递给函数,数组的sizeof变为4的原因

C语言中,数组名作为参数传递给函数时,退化为指针,sizeof对指针操作结果应该是4.例子如下: #include<iostream> using namespace std; void Swap_arr(char* charArr){ int len = sizeof(charArr); cout << "len =" << len << endl; //输出len =4 } int main(){ char charArr[] = &

C语言,数组名,指针常量和常量指针

自己给自己劝退一波~ 先介绍指针常量和常量指针 const int *p; //这是个指针常量 int const* p; //这是个常量指针 const是常量修饰符,被修饰的就是一个常量,常量的特性就是不能改变. 先介绍指针常量, const int *p; int i=2; p=&i; 这里*p就是一个常量,他的值不能改变,也就是不能再通过*p=1; 这样赋值而去改变 i 的值,但可以通过直接i=1;这样改变i的值,此时*p的值也相应变为了1 int const* p=NULL; int i

c语言中数组名和指针变量的区别

编译器工作原理:在64位的计算机中,当创建一个指针变量时,计算机会为它分配8个字节的存储空间.但如果创建的是数组呢?计算机会为数组分配存储空间,但不会为数组变量分配任何空间,编译器仅在出现它的地方把它替换成数组的起始地址. 结论1:由于计算机没有为数组变量分配空间,也就不能把它指向其他地方.例题: char s[]="How big is it?"; char *t=s; //正确,将数组的地址赋给指针变量t s=t; //错误,数组变量没有存储空间,无法存储指针变量t的值,编译报错