当前位置: 首页 > 编程日记 > 正文

从*p++说指针,数组,结构和函数

说明文中*p++和*s++都是一个东西,不做字面上的统一了。

因为右结合性,*p++ 其实就是 *(p++) 


1.strlen的实现

#include <stdio.h>
main(){char str[]= "Abcde";printf("\n string = %s length = %d \n",str,str_length(str));
}int str_length (const char *s){int length = 0;while (*s++){length++;}return (length);
}
其实*s++的过程




递增到最后一位就是\0,也就是“”.


注意:*s已经指向后面的内容了,就是乱码了



2.数组和指针这2种方式表示字符串的差异
#include <stdio.h>
main( )
{char  str[]= "Abcde";char*  ptr = "12345";*ptr++;printf ("\n string = %s length = %d \n",ptr,str_length (ptr));printf ("\n string = %s length = %d \n",str,str_length (str));
}int str_length (const char  *s)
{int length = 0;while (*s++){length++ ;}return (length) ;
}
输出:


2.1 数组不能直接当指针用,数组名不能指针运算
也就是说数组名代表数组的首元素,它是一个指针常量,它的值在程序运行期间是固定不变的,  *str++是不可以的;
ptr是指针变量当然可以实现ptr++的运算但是指针自然可以指针运算。


直接数组名++就报错了:


2.2 数组名不能直接赋值,但是指针可以

给数组名赋值就报错了:


第1次指针地址是:0x010f5860


第2次指针地址是:0x010f5861


第3次指针地址是:0x010f5868


第4次指针地址还是:0x010f5868


下面是《明解C语言》书的截图:


3.  int下*s++,(*s)++,++*s,++(*s)的差异
首先 如果*s是指针,那么*s++就不是将*s的值加1,而是将*s指向的地址加同一个单位大小。所以为了避免类似问题,需要的时候要加括号。

--出自《C语言入门经典 第4版》

#include <stdio.h>
void add(int *s)
{*s++;
}int str_length (char  *s)
{int length = 0;while (*s++){length++ ;}return (length) ;
}main( )
{int a=1;int *b=&a;char  str[]= "Abcde";char*  ptr = "12345";*ptr++;ptr="def";add(b);printf ("\n string = %s length = %d \n",ptr,str_length (ptr));printf ("\n string = %s length = %d \n",str,str_length (str));
}


第1次*s++之前的地址是:0x002afc98


第2次*s++之前的地址是:0x002afc9c
fc9c-fc98=4  就是一个int的大小
*s++只是对s的地址递增然后解引用,得到-858993460,并没有改变*s的值!


跳出函数a没有变化


所以要想得到Int型值的递增可以这样写即可:
void add(int *s)
{(*s)++;
}

由于char*大小正好是1个字节,所以char*的++正好指向下一个字符
所以在字符串的操作中正好可以用*s++,如果使用了括号,(*s)++这样的话反而会引起内存错误。

4.字符串复制
#include <stdio.h>void xstrcpy ( char  *t, char  *s ){while ( *s != '\0' ){*t = *s ;s++ ;t++ ;}*t = '\0' ;
}void strcpy(char *s,char *t){//while((*s++=*t++)!='\0')//表达式通'\0'的比较是多余的,因为只需要判断表达式的值是否为0即可。while(*s++=*t++);
}//标准库实现
char * strcpy2(char *s,char *t){
char *r=s;while(*s++=*t++);return r;
}void main()
{char  source[] = "Abcde" ;char  target[20] ;strcpy ( target, source ) ;printf ( "\nsource string = %s", source ) ;printf ( "\ntarget string = %s", target ) ;
}
/*
想经过函数调用改变某个变量的值,就要传入变量的地址。如果变量是基本类型,要传入对应的指针类型。如果变量是指针,要传入指针的指针。*/


--出自《C语言程序设计语言 第2版》



5.说清楚函数传递参数


一开始我们会想既然已经在函数中*s++了,而且也确实改变了指针的位置,但是为什么一回到调用函数中,*s就又复原了?
不是说传指针是按引用传递的么?

其实,误区也正在于此,函数还是传值的,传递的都是原值的拷贝,如果传递指针,在调用函数中使用*解引用,可以改变指针指向的值,但是不能改变指针的内容,因为函数调用只是传递了原始指针指向值地址的拷贝,就是说原始地址拷贝了2份,所以在函数中改变是改变了地址,但是没有意义。


int a = 0x55aa;

change_value(&a, 0xaa55);

这样a的值改变了,真正的情况是参数传递后,编译器做了一个参数拷贝过程,比如声明一个整型指针pCopy = &a;

这样,pCopy只是传进来参数&a的一份拷贝,但是他们都指向了a的地址,因此用这种方法可以改变a 的值。


那么现在有个问题,通过传递一个指针,可以改变该指针所指向地址的内容,那么如何改变指针本身呢?
该怎么做才能改变ptr呢?

既然ptr也是一个变量,我要在函数内部改变它,那么就传递一个指向ptr的指针!也就是二级指针!



6.函数返回指针

绝不返回函数中本地变量的地址


函数返回指针可以用如下方法:

1.可以用malloc分配内存,并返回这个内存的地址

2.返回指针参数


注意函数中可以声明一个新的结构struct,然后返回结构,但是不可以返回临时指针



7.数组和指针的差异
数组不是指针,作为参数传递的数组会退化为指针。





为什么C语言把数组形参当做指针?



再来看看《你必须知道的495个C语言问题》



8.数组不能被赋值
数组不能赋值,可以指定数组下标赋值,可以在函数中可以给数组赋值,因为这个时候数组退化为指针。




9.数组的大小




10.指针和结构

结构体指针4个字节结构体大小要看数据对齐
分配12个字节,结构吃掉8个,当 (结构地址+1)所以只能第一个元素可以分配到初始化的0,第二个元素就分到垃圾地址了

struct tt{int size;int slabs;
};
void main()
{void *s=malloc(12);struct tt *t1;memset(s,0,12);t1=(struct tt*)s;t1->size=1;t1->slabs=2;
}

指针不对齐8a88  和8a90差2   8a90和8a98差8    结构有2个Int  所以结构大小是8

结构和指针的关系
对同一个地址可以转换为任意结构体,虽然数据结构乱了,但是毕竟也是有数据。
所以使用法则也就是使用前先寻址,再强制转换


11.变量作用域

局部变量的作用域一般认为是在函数体内。但是根据C99标准,该说法有了变化。在新的标准中,允许即时定义局部变量,示例如下:

for( int i = 0; i < MAXSIZE; i++ )

{

….

}

例子中的局部变量i的作用域即在for循环的花括号中,当for循环结束的时候,局部变量i的生存周期同时结束。也就是说,在下一个for循环中,你仍然可以再次重新定义并使用名为i的局部变量。该语法只能在C99之后的新的C编译器中使用, 例如VC2005、VC2008、gcc4.2及以上版本。但是,该语法带来了编程风格的变化,而且变量隐含在了执行程序中,无论是代码的阅读和维护都有较大的困难,因此工程项目中不建议使用该语法。


for循环中定义的pit 在离开循环以后就不存在了。


12.传递结构和数组给函数的差异

为什么传递给函数的结构没有像数组一样退化为指针,因为数组可以用指针去偏移量,但是结构无法做到这一点,或者说非常困难。

其实函数参数默认是通过r0,r1,r2,r3四个寄存器传递的,多余的参数是通过将参数压入栈中传递的。同理对于一个结构体如果其大小少于32字节(4个寄存器),按照正常的方式通过r0到r3传递,多于32字节则是将多余的部分在堆栈上建立个备份进行传递。

所以对于在ADS编译器下对于函数参数是结构体的传递,还是传入指针比较好。既高效(省去建立备份的时间),又节省栈空间。


13.指针大小

32位是4个字节,32=4*8     

64位是8个字节,64=8*8

在64位的linux下:

而visual studio里默认是win32平台,指针是4个字节大小:


需要修改为x64平台

这时候显示指针是8个字节:



14.指向数组的指针
slabclass_t *p = &slabclass[id];


相关文章:

8比特数值也能训练模型?商汤提训练加速新算法丨CVPR 2020

出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09;在CVPR 2020上&#xff0c;商汤研究院链接与编译团队、高性能计算团队和北航刘祥龙老师团队合作提出了用于加速卷积神经网络训练过程的INT8训练技术。该工作通过将网络的输入、权重和梯度量化到8比特来加速网络的前向传…

×××作,不知写些什么

博客&#xff0c;老是有写的冲动&#xff0c;不过&#xff0c;没什么韧劲坚持&#xff0c;自己感觉文采一般般啦&#xff0c;有时兴起&#xff0c;挥毫泼墨&#xff0c;蜡笔重唱一番&#xff0c;呵呵&#xff0c;自个爽朗了&#xff0c;呵呵 所以&#xff0c;自己坚持&#xff…

centos7 install 安装mysql

CentOS 7的yum源中貌似没有正常安装mysql时的mysql-sever文件&#xff0c;需要去官网上下载 # wget http://dev.mysql.com/get/mysql-community-release-el7-5.noarch.rpm # rpm -ivh mysql-community-release-el7-5.noarch.rpm # yum install mysql-community-server成功安装之…

AI四巨头Google、DeepMind、Microsoft、Uber深度学习框架大比拼

编者按&#xff1a;Google、Uber、DeepMind和Microsoft这四大科技公司是当前将深度学习研究广泛应用于自身业务的典型代表&#xff0c;跻身全球深度学习研究水平最高的科技公司之列。GPipe、Horovod、TF Replicator和DeepSpeed分别是这四家公司开发应用的深度学习框架&#xff…

转《刘润的数字化家庭》

数字家庭也是我的一大梦想&#xff0c;感谢刘润让我的想法更加丰富和具体。。。 转载自刘润的博客&#xff0c;原文地址&#xff1a;http://blog.run2me.com/runliu/archive/2010/06/12/37082.aspx 1 of 22 &#xff08;大图&#xff09;&#xff1a;用数字化的技术&#xff0c…

自己写的内存池Slabs

看memcached的源码写的&#xff0c;虽然很粗糙&#xff0c;但是基本思想还是有的&#xff0c;自娱自乐&#xff0c;后期不断改进。 #include <stdio.h> #include <stdlib.h> #include <string.h>struct st{void * start;void * end;char ptr[10]; }; struct …

Eclispse Che(2):启动Che服务,进入IDE界面

本文的原文连接是: http://blog.csdn.net/freewebsys/article/details/50888878 未经博主允许不得转载。 博主地址是&#xff1a;http://blog.csdn.net/freewebsys 1&#xff0c;关于Docker 上次使用Che的时候没有成功创建Project。 其实主要问题就是docker的网络问题。 使用…

使用strace和ltrace跟踪程序调用

ltrace能够跟踪进程的库函数调用,它会显现出哪个库函数被调用,而strace则是跟踪程序的每个系统调用.1.系统调用的输出对比程序代码&#xff1a;#include <stdio.h> main(){char str[] "Abcde";printf("\n string %s length %d \n",str,str_length(…

NeHe OpenGL第三十三课:TGA文件

NeHe OpenGL第三十三课&#xff1a;TGA文件 加载压缩和未压缩的TGA文件: 在这一课里&#xff0c;你将学会如何加载压缩和为压缩的TGA文件&#xff0c;由于它使用RLE压缩&#xff0c;所以非常的简单&#xff0c;你能很快地熟悉它的。 我见过很多人在游戏开发论坛或其它地方询问…

阿里自动驾驶新突破!达摩院自研ISP图像处理器大幅提升安全性

阿里巴巴达摩院在自动驾驶领域取得新突破&#xff01;4月8日&#xff0c;据记者了解&#xff0c;达摩院已经自主研发出用于车载摄像头的ISP处理器&#xff0c;保障自动驾驶车辆在夜间拥有更好的“视力”&#xff0c;“看”得更清晰&#xff0c;从而大幅提升自动驾驶安全性, 而背…

3月14号作业

<!DOCTYPE html> <html> <head lang"en"><meta charset"UTF-8"><title></title> </head> <body> <br/> <br/> <img src"51job表单_03.gif"</br> <br/> <br/>…

NeHe OpenGL第三十五课:播放AVI

NeHe OpenGL第三十五课&#xff1a;播放AVI 在OpenGL中播放AVI: 在OpenGL中如何播放AVI呢&#xff1f;利用Windows的API把每一帧作为纹理绑定到OpenGL中&#xff0c;虽然很慢&#xff0c;但它的效果不错。你可以试试。 首先我得说我非常喜欢这一章节.Jonathan de Blok使我产生…

为什么TCP的TIME_WAIT状态要保持2MSL?

TIMEWAIT状态也称为 2MSL等待状态。每个具体TCP实现必须选择一个报文段最大生存时间MSL(Maximum Segment Lifetime)。它是任何报文段被丢弃前在网络内的最长时间。我们知道这个时间是有限的&#xff0c;因为TCP报文段以IP数据报在网络内传输&#xff0c;而IP数据报则有限制其生…

深度 | 一文读懂“情感计算”在零售中的应用发展

作者 | 黄程韦博士、刘刚、包飞博士、杨现博士、孙皓博士、沈艺博士来源 | 苏宁零售技术研究院零售商需要不断通过创新服务来提高顾客的购物体验&#xff0c;而情感计算在该领域具有独特优势。它在零售行业的应用&#xff0c;主要集中在提升购物体验的服务中。在这个科技逐步改…

mysql基于replication实现最简单的M-S主从复制

2019独角兽企业重金招聘Python工程师标准>>> 什么是replication Replication可以实现数据从一台数据库服务器&#xff08;master&#xff09;复制到一到多台数据库服务器。 默认情况下&#xff0c;属于异步复制&#xff0c;因此无需维持长连接。 通过配置&#xff0…

Linux下高并发socket最大连接数所受的各种限制

修改最大打开文件数 # ulimit -n 修改最大进程数 # ulimit -u ------------------------------------------------------ Linux下高并发socket最大连接数所受的各种限制 转自&#xff1a;http://blog.csdn.net/guowake/article/details/6615728 1、修改用户进程可打开…

linux安全问答(1)

一、如何限制对系统资源的过度使用&#xff1f; &#xff08;1&#xff09;、编辑/etc/security/limits.conf文件&#xff0c;在其中加入或改变下面这些内容&#xff1a; * hard core 0 //禁止创建core文件 * hard rss 5000 //表示除root用户之外&#xff0c;其他用户都只能最多…

快速搭建对话机器人,就用这一招!

作者 | Milvus.io 责编 | 胡巍巍问答系统是自然语言处理领域一个很经典的问题&#xff0c;它用于回答人们以自然语言形式提出的问题&#xff0c;有着广泛的应用。其经典应用场景包括&#xff1a;智能语音交互、在线客服、知识获取、情感类聊天等。常见的分类有&#xff1a;生成…

目前流行的源程序版本管理软件和项目管理软件都有哪些?各有什么优缺点?...

目前流行的源程序版本管理软件和项目管理软件&#xff1a;Microsoft TFS&#xff0c;Github&#xff0c;SVN&#xff0c;Coding 各自的优缺点&#xff1a; Microsoft TFS&#xff1a;优点&#xff1a;任务版上能将需求、项目进度一览无余&#xff0c;对于小团队而言&#xff0c…

孙鑫mfc学习笔记第十四课

第十四课网络的相关知识&#xff0c;网络程序的编写&#xff0c;Socket是连接应用程序与网络驱动程序的桥梁&#xff0c;Socket在应用程序中创建&#xff0c;通过bind与驱动程序建立关系。此后&#xff0c;应用程序送给Socket的数据&#xff0c;由Socket交给驱动程序向网络上发…

Linux环境编译安装Mysql以及补装innodb引擎方法

mysql安装 5.6以后可能会收费&#xff0c;所以选择5.1以下从台湾中山大学镜像下载 1.首先要安装C编译环境 # yum install gcc-c 2.下载解压 # wget http://mysql.cdpa.nsysu.edu.tw/Downloads/MySQL-5.1/mysql-5.1.73.tar.gz# tar zxvf mysql-5.1.73.tar.gz# cd mysql-5…

Python 炫技操作:合并字典的七种方法

来源 | Python编程时光&#xff08;ID: Cool-Python&#xff09;Python 语言里有许多&#xff08;而且是越来越多&#xff09;的高级特性&#xff0c;是 Python 发烧友们非常喜欢的。在这些人的眼里&#xff0c;能够写出那些一般开发者看不懂的高级特性&#xff0c;就是高手&am…

shell脚本编程基础(1)及RAID阵列

shell脚本&#xff1a;Linux从底层到上层的系统架构&#xff1a;硬件-->内核-->库(lib)-->shell-->用户。shell既是一种命令语言&#xff0c;也是程序设计语言&#xff08;shell脚本&#xff09;&#xff0c;作为一种命令语言&#xff0c;它提供了用户与内核的交互…

freemarker基本语法及实例

EG.一个对象BOOK 1.输出 ${book.name} 空值判断&#xff1a;${book.name?if_exists }, ${book.name?default(‘xxx’)}//默认值xxx ${ book.name!"xxx"}//默认值xxx 日期格式&#xff1a;${book.date?string(yyyy-MM-dd)} 数字格式&#xff1a;${boo…

前百度主任架构师创业,两年融资千万美元,他说AI新药研发将迎来黄金十年...

「AI技术生态论」 人物访谈栏目是CSDN发起的百万人学AI倡议下的重要组成部分。通过对AI生态专家、创业者、行业KOL的访谈&#xff0c;反映其对于行业的思考、未来趋势的判断、技术的实践&#xff0c;以及成长的经历。2020年&#xff0c;CSDN将对1000人物进行访谈&#xff0c;形…

Linux环境安装卸载JDK以及安装Tomcat和发布Java的web程序

Linux环境&#xff1a;CentOS7.2 一.安装JDK 安装好的CentOS会自带OpenJdk&#xff0c;最好还是先卸载系统自带的JDK&#xff0c;然后自己重新去Oracle网站下载最新的JDK安装。 1.卸载系统自带的JDK 查看java信息 # java -version 查看JDK # rpm -qa | grep java 或者 还…

(转)详解css3弹性盒模型(Flexbox)

今天刚学了css3的弹性盒模型&#xff0c;这是一个可以让你告别浮动、完美实现垂直水平居中的新特性。 Flexbox是布局模块&#xff0c;而不是一个简单的属性&#xff0c;它包含父元素和子元素的属性。 Flexbox布局的主体思想是似的元素可以改变大小以适应可用空间&#xff0c;当…

Java开发环境的搭建以及使用eclipse创建项目

一、Java 开发环境的搭建 这里主要说windows环境下怎么配置Java环境。如果是Linux环境参考本博客另一篇文章即可&#xff1a; Linux环境安装卸载JDK 1.首先安装JDK java的SDK简称JDK。 去官网下载最新的JDK即可&#xff1a; http://www.oracle.com/technetwork/java/javase…

​MMIT冠军方案 | 用于行为识别的时间交错网络,商汤公开视频理解代码库

作者 | 商汤出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09;本文主要介绍三个部分&#xff1a;一个高效的SOTA视频特征提取网络TIN&#xff0c;发表于AAAI2020ICCV19 MMIT多标签视频理解竞赛冠军方案&#xff0c;基于TIN和SlowFast一个基于PyTorch&#xff0c;包含大…

MySQL的主从服务器配置

MySQL的主从服务器配置常见开源数据库有&#xff1a;MySQL&#xff0c;PostgreSQL&#xff0c;SQLite等&#xff0c;商业性质的&#xff1a;Oracle&#xff0c;Sql Server&#xff0c;DB2&#xff0c;Sybase&#xff0c;Infomix其中&#xff0c;Oracle的版本有Oracle 11g,Oracl…