IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C语言13 指针与数组2=数组名的本质+数组名作首地址+数组做函数参数+sizeof指针 -> 正文阅读

[C++知识库]C语言13 指针与数组2=数组名的本质+数组名作首地址+数组做函数参数+sizeof指针

一、数组名的本质

(1)数组名指代一种数据结构,这种数据结构就是数组;

例如:

char str[10];

cout << sizeof(str) << endl;?

输出结果为10,str指代数据结构char[10]。

(2)数组名可以转换为指向其指代实体的指针,而且是一个指针常量,不能作自增、自减等操作,不能被修改;

char str[10];

str++; //编译出错,提示str不是左值 

(3)数组名作为函数形参时,沦为普通指针。

Windows NT 32位平台下,指针的长度(占用内存的大小)为4字节,故sizeof( str ) 、sizeof ( p ) 都为4。

===================数组名做函参====================

实参数组名代表数组的首地址,而形参是用来接收从实参传递过来的数组首地址。形参是一个指变才能存地址,C编译时也把形参数组当指变来处理。

@ f(int art[ ],int n)等价f(int *art,int n);

a、调用函数的时候,系统会建立一个指针变量arr,用来存放从主调函数传过来的实参数组首地址。

b、可以认为有一个形参数组从实参数组那里得到起始地址,二者共同占同一段内存单元,调用函数期间,若改变了形参数组的值,也就是改变了实参数组的值。

c、有一个实参数组,想在函数中改变其元素的值,实参与形参的对应关系应该如下:

(1)实参和形参都用数组名。(认为两个数组公用一段内存单元)

(2)实参用数组名,而形参用指变。

(3)实参形参皆用指变。(二者共指向同一内存单元)

(4)实参为指变,而形参为数组。(形参的数组名也将作为指变来处理。)

@使用指变做实参,必须先使指变有确定的值,指向一个已经定义好的数组。

举例:以下代码中的两个sizeof用法有问题吗?

#include <stdio.h>
#include <iostream>
using namespace std;

/* 
功能:将 str 中的小写字母转换成大写字母
备注:不管传的是数组或是指针,最后编译都会转换成为指针,也就是地址,是指向参数的首地址的指针。
因为是地址所以是4个字节,32位。
*/
void UpperCase( char str[]) 
{ 
      int i;   
      for(i=0;  i<sizeof(str)/sizeof(str[0]); ++i)
      {
          if( 'a'<=str[i] && str[i]<='z')
                     str[i] -= ('a'-'A' );	//由小写转大写
      }
//错误!sizeof(str)是指针的大小4,只循环了4次。数组做参数,会退化为指针。可改为strlen(str)
}

void main()
{
       char str[] = "aBcDefg";
       cout << "str字符长度为: "<< sizeof(str)/sizeof(str[0])<< endl;//是数组的大小8
       UpperCase(str);
       cout <<str<< endl;  
}

答:函数内的sizeof有问题。根据语法,sizeof如用于数组,只能测出静态数组的大小,无法检测动态分配的或外部数组大小。函数外的str是一个静态定义的数组,因此其大小为8。函数内的str作为函数参数时,退化为指针,实际只是一个指向字符串的指针,没有任何额外的与数组相关的信息,因此sizeof作用于上只将其当指针看,一个指针为4个字节,因此返回4。

二、数组名作为首地址

1、指出下面代码的输出,并解释为什么。

main()
{
	int a[5]={1,2,3,4,5};
	int *ptr=(int *)(&a+1);//指针是数组类型,+1相当于加20.如果是(a+1)是+4
	printf("%d  %d\n", a, ptr); 
	printf("%d, %d", *(a+1),*(ptr-1));
}

输出:1245036 1245056 2,5

*(a+1)就是a[1],*(ptr-1)就是a[4],执行结果是2,5

&a+1不是首地址+1,系统会认为加一个a数组的偏移,是偏移了一个数组的大小(本例是5个int).

int *ptr=(int *)(&a+1);

则ptr实际是&(a[5]),也就是a+5

原因如下:

&a是数组指针,其类型为 int (*)[5];

而指针加1要根据指针类型加上一定的值,不同类型的指针+1之后增加的大小不同

a是长度为5的int数组指针,所以要加 5*sizeof(int),所以ptr实际是a[5].

但是prt与(&a+1)类型是不一样的(这点很重要),所以prt-1只会减去sizeof(int*).

a,&a的地址是一样的,但意思不一样,a是数组首地址,也就是a[0]的地址,&a是对象(数组)首地址,a+1是数组下一元素的地址,即a[1],&a+1是下一个对象的地址,即a[5]。

2、题目如下,找出其中的不妥之处。

char *p1, *p2;
char ch[12];
char **pp;
p1 = ch;  //指向数组首地址 &ch[0]
pp = &ch; //错误用法

p2 = *pp;
问p1和p2是否相同

答:首先,数组ch是没有初始化的。其次,一个比较隐含的地方是,数组名可以代表数组第一个元素的首地址,这个没有问题,但是,数组名并非一个变量,数组分配完成后,数组名就是固定的,地址也是固定的。这样导致的结果就是绝对不能把数组名当作变量来进行处理。上述题目中,pp=&ch,显然是把数组名当作指针变量来使用了,这样肯定出问题。

三、sizeof(指针)

@@指针的涵义:其本身内存中的一个地址,存储指向内容的地址。

char *p=str;

区别sizeof(p)和sizeof(*p); p=&str[0]; *p=str[0];*(p+1)=str[1];

区别sizeof(p)和cout<<p<<str<<endl;输出字符串和获取指针大小。

1、以下为Windows NT下的32位C++程序,请计算sizeof的值:


{
    char str[]="hello";       //sizeof(str)=6;  //str代表hello数组首地址
    char *p=str;	          //sizeof(p)=4;    //是对P指针本身求取地址
                              //sizeof(*p) = 1;  //*p=str[0]
    int n;		              //sizeof(n)=4;    //相当于sizeof(int);
    void *p= malloc(100);     //sizeof(p)=4; //求取的是指针本身,不是它所指向的内容。
}

   void Func(char str[100])
   {
       sizeof(str)=4; //数组名作为函数形参,沦为普通指针。
   }

Func ( char str[100] )函数中数组名作为函数形参时,在函数体内,数组名失去了本身的内涵,仅仅只是一个指针;在失去其内涵的同时,它还失去了其常量特性,可以作自增、自减等操作,可以被修改。

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-08-08 11:03:10  更:2021-08-08 11:06:47 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/9 14:39:24-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码