C基础梳理 2018.12.31 (函数调用栈、栈的生长方形和内存存放方向、大小端、指针、字符串、字符串拷贝、格式化字符串_sprintf)

函数调用的流程

 

宏函数不是函数

他只是预处理器进行简单的文本替换,以空间换时间

#include<iostream>
using namespace std;

#define MYADD(x,y) ((x)+(y))
#define MAX 1024

int main() {
	int a = 10;
	int b = 20;

	cout << "a+b=" << MYADD(a, b) << endl;
	return 0;
}

宏的细节,参考这个:C++宏定义详解

 

栈总是向下增长压栈操作使得栈顶地址减小,出现操作使得栈顶地址增加。

栈保存一个函数调用中所需要维护的信息,这通常被称为活动记录,一个函数迪奥哟经过程所需要的信息一般包括以下几个方面:

  1. 函数的地址
  2. 函数的参数
  3. 临时变量
  4. 保存的上下文:包括在函数迪奥哟经前后需要保持不变的寄存器。

 

 

 

函数参数的传递顺序和方式

最常见的函数传递方式是栈传递。函数的调用方将参数压入栈中,函数自己再从栈中将参数取出。对于有多个参数的函数,调用管理要规定函数调用方将参数压栈的顺序:从左向右或者从右向左。有些调用惯例还允许使用寄存器传递参数,以提高性能。

 

栈的维护方式

在函数将参数压入栈中之后,函数体会被调用,此后需要将被压入栈中的参数全部弹出,以使得栈在函数调用前后保持一致。这个弹出的工作可以由函数的调用方完成或者函数自己完成。

 

 

 

 

 

栈的生长方向和内存存放方向

 

 

大小端

#include<stdio.h>

void test() {
	int a = 0xaabbccdd;
	unsigned char*p = &a;
	printf("%x\n", *p);
	printf("%x\n", *(p+1));
}

int main() {
	test();
	return 0;
}

运行结果:

说明高位字节被存放在了高地址低位字节存放在了低地址——小端模式

 

 

 

指针

 

1、指针就是一个变量

2、指针不管什么类型,不管几级指针,占4字节

 

野指针

指向已经删除的对象申请访问受限内存区域的指针。野指针无法通过简单的判断是否为空来进行避免,只能通过养成良好的变成习惯来尽量减少。对野指针进行操作很容易出现程序错误。

 

什么情况会产生野指针

1、指针变量未初始化

2、指针释放后未置空

3、指针操作超过变量作用域

 

 

指针的步长:指针变量+1,要向后跳多少字节

 

指针的类型不仅仅决定指针的步长,还决定解引用的时候从给定地址开始取类型大小的字节数

例子如下:

#include<stdio.h>
#include<cstring>

void test() {
	char buf[1024] = { 0 };
	int a = 100;
	//将a中的内容拷贝到buf中,拷贝的字节大小为sizeof(int)
	memcpy(buf , &a, sizeof(int));

	char *p3 = buf;
	//(int*)说明我要去的内容类型为int,因此会取四字节的内容
	//*代表解引用,将p3指向的地址上的内容取出来
	printf("*(int*)(p3)= %d\n", *(int*)(p3 ));
}

int main() {
	test();
	return 0;
}

运行结果:

 

 

 

字符串

字符串基础

 

1、不设置结尾标识符'\0',也不设置长度的结果

#include<stdio.h>
#include<cstring>

void test() {
	char str[] = { 'h','e','l','l','0' };
	printf("%s\n", str);
}

int main() {
	test();
	return 0;
}

运行结果:

 

2、设置长度之后,未赋值部分自动初始化为 0

#include<stdio.h>
#include<cstring>

void test() {
	char str[100] = { 'h','e','l','l','0' };
	printf("%s\n", str);
}

int main() {
	test();
	return 0;
}

运行结果:

 

3、以字符串初始化,那么编译器默认会在字符串尾部添加“\0”

#include<stdio.h>
#include<cstring>

void test() {
	char str[] = "hello";
	printf("%s\n", str);
}

int main() {
	test();
	return 0;
}

运行结果:

 

 

 

 

字符串拷贝

#include<stdio.h>
#include<cstring>

void copyStr(char * dst, const char *source) {
	int len = strlen(source);
	for (int i = 0; i < len; i++) {
		dst[i] = source[i];
	}
}


void test() {
	const char *source = "hello world!";
	char buf[1024] = { 0 };
	copyStr(buf, source);
	printf("%s\n", buf);
}

int main() {
	test();
	return 0;
}

运行结果:

 

如果把上述代码中的char buf[1024] = { 0 }; 改成char buf[1024]; 则运行结果变为:

 

应对策略,咋copyStr函数中经加上 dst[len]='\0';

#include<stdio.h>
#include<cstring>

void copyStr(char * dst, const char *source) {
	int len = strlen(source);
	for (int i = 0; i < len; i++) {
		dst[i] = source[i];
	}
	dst[len] = '\0';
}


void test() {
	const char *source = "hello world!";
	char buf[1024];
	copyStr(buf, source);
	printf("%s\n", buf);
}

int main() {
	test();
	return 0;
}

运行结果

 

也可以通过指针进行字符串拷贝

#include<stdio.h>
#include<cstring>

void copyStr(char * dst, const char *source) {
	while (*source )
		*dst++ = *source++;
	*dst = '\0';
}


void test() {
	const char *source = "hello world!";
	char buf[1024];
	copyStr(buf, source);
	printf("%s\n", buf);
}

int main() {
	test();
	return 0;
}

运行结果

 

 

 

格式化字符串_sprintf

 

1、格式化字符串

#include<stdio.h>

void test() {
	char buf[1024] = { 0 };
	sprintf(buf, "hello %s!", "Obama");
	printf("%s\n", buf);
}

int main() {
	test();
	return 0;
}

运行结果:

 

 

2、拼接字符串

#include<stdio.h>

void test() {
	char buf[1024] = { 0 };
	char *s1 = "hello";
	char* s2 = "world";
	sprintf(buf, "%s %s!", s1,s2);
	printf("%s\n", buf);
}

int main() {
	test();
	return 0;
}

运行结果:

 

 

3、数字转成字符串格式

#include<stdio.h>

void test() {
	char buf[1024] = { 0 };
	int num = 666;
	sprintf(buf, "%d!", num);
	printf("%s\n", buf);
}

int main() {
	test();
	return 0;
}

运行结果

 

 

4、格式化输出八进制、十六进制

#include<stdio.h>

void test() {
	char buf[1024] = { 0 };
	int num = 666;
	sprintf(buf, "%o", num);
	printf("%s\n", buf);
}

int main() {
	test();
	return 0;
}

运行结果:

 

十进制数字格式化成16进制字符串

#include<stdio.h>

void test() {
	char buf[1024] = { 0 };
	int num = 666;
	sprintf(buf, "%x", num);
	printf("%s\n", buf);
}

int main() {
	test();
	return 0;
}

运行结果:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值