目录
1、总结:c语言中“#if 0 / #if 1 ... #endif”的作用:
1、(成功)double:占用空间8字节(int的2倍);char占用1字节;
1、(成功)struct:只有char时候,struct占用1字节空间
1、(成功)struct:只有int时候,struct占用4字节空间
1、(疑问-已解决)struct同时有int和char时候,占用8字节空间;这是为什么呢?
1、(成功)栈区的内存自动申请释放、不需要程序手动管理+我们并不关心值是多少,因为局部变量a的内存已经被回收
1、测试1(成功)堆的内存成员手动申请,手动释放+只要是连续的内存空间,都能使用下标的方式访问内存
①为什么为空:理解2:验证理解1:所以我直接不运行allocateSpace函数了,输出还是空,因此我传递给allocate里面实参后,就和test02里面的char *p没有关系了,
1、头文件不能参与编译,每一个.c文件,我们叫做一个编译单元;编译器独立编译每一个.c文件
1、(失败-按照课程源码编写也是报错,不知道是什么情况)测试2:
一、目的
1、想多学习C知识
二、参考
1、(01)某马C++24期完整版
三、操作:一:01 typedef用法
1、总结:c语言中“#if 0 / #if 1 ... #endif”的作用:
(1)code中定义的是一些调试版本的代码,此时code完全被编译器忽略。如果想让code生效,只需把#if 0改成#if 1
(2)#if 0还有一个重要的用途就是用来当成注释,如果你想要注释的程序很长,这个时候#if 0是最好的,保证不会犯错误。
(但是林锐的书上说千万不要把#if 0 来当作块注释使用) #if 1可以让其间的变量成为局部变量。
(3)这个结构表示你先前写好的code,现在用不上了,又不想删除,就用这个方法,比注释方便。
1、总结:typedef用法
typedef是在计算机编程语言中用来为复杂的声明定义简单的别名,它与宏定义有些差异。
它本身是一种存储类的关键字,与auto、extern、mutable、static、register等关键字不能出现在同一个表达式中。
1、总结:typeid
在c++中,typeid用于返回指针或引用所指对象的实际类型。
1、(成功)运行效果:
#include <iostream>
using namespace std;
/*
c语言中“#if 0 / #if 1 ... #endif”的作用:
(1)code中定义的是一些调试版本的代码,此时code完全被编译器忽略。如果想让code生效,只需把#if 0改成#if 1
(2)#if 0还有一个重要的用途就是用来当成注释,如果你想要注释的程序很长,这个时候#if 0是最好的,保证不会犯错误。
(但是林锐的书上说千万不要把#if 0 来当作块注释使用) #if 1可以让其间的变量成为局部变量。
(3)这个结构表示你先前写好的code,现在用不上了,又不想删除,就用这个方法,比注释方便。
*/
#if 0
struct Person
{
char name[64];
int age;
};
/*
typedef是在计算机编程语言中用来为复杂的声明定义简单的别名,它与宏定义有些差异。
它本身是一种存储类的关键字,与auto、extern、mutable、static、register等关键字不能出现在同一个表达式中。
*/
typedef struct Persion myPersion;
#endif
typedef struct Person
{
char name[64];
int age;
} myPerson;
void test01()
{
myPerson p;
}
typedef char * PCHAR;
void test02()
{
char *p1, *p2;
//在c++中,typeid用于返回指针或引用所指对象的实际类型。
cout << typeid(p1).name() << endl;
cout << typeid(p2).name() << endl;
}
typedef int mytype_t;
//有利于程序的移植性
void test03()
{
mytype_t a;
}
int main()
{
//test01();
test02();
//test03();
system("pause");
return EXIT_SUCCESS;
}
四、操作:二:sizeof用法
1、(成功)int占用空间大小:4字节
1、(成功)double:占用空间8字节(int的2倍);char占用1字节;
1、(成功)struct:只有char时候,struct占用1字节空间
1、(成功)struct:只有int时候,struct占用4字节空间
1、(疑问-已解决)struct同时有int和char时候,占用8字节空间;这是为什么呢?
答:①、原来struct会多分配空间,允许你浪费
五、操作:三:栈区
1、(成功)栈区的内存自动申请释放、不需要程序手动管理+我们并不关心值是多少,因为局部变量a的内存已经被回收
2、(失败-未解决)printf输出乱码
①出现问题:printf乱码
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
char *getString()
{
char str[] = "hello world!";
return str;
}
void test02()
{
char *s = NULL;
s = getString();
printf("s = %s\n", s);
}
int main()
{
//Test01();
test02();
system("pause");
return EXIT_SUCCESS;
}
①解决方法:一:失败:添加了\0还是不行
①解决方法:二:失败:修改编码,改为UTF-8:
①解决方法:三:失败:使用cout输出
六、操作:四:堆区
1、测试1(成功)堆的内存成员手动申请,手动释放+只要是连续的内存空间,都能使用下标的方式访问内存
①运行结果
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
using namespace std;
//1、堆的内存成员手动申请,手动释放
int * getSpace()
{
int *p = (int *)malloc(sizeof(int) * 5);
if (NULL==p)
{
return NULL;
}
int j = 0;
//只要是连续的内存空间,都能使用下标的方式访问内存
for (int i = 0; i < 5;i++)
{
p[i] = 100 + i;
}
return p;
}
void test01()
{
int *ret = getSpace();
for (int i = 0; i < 5;++i)
{
printf("%d\n", ret[i]);
}
//用完堆内存,一定要释放
free(ret);
ret = NULL;
}
int main()
{
test01();
system("pause");
return EXIT_SUCCESS;
}
2、测试2(失败-未解决-有自己的理解):
①运行结果:疑问:为什么这个可以输出内容是空
- memset是计算机中C/C++语言初始化函数。作用是将某一块内存中的内容全部设置为指定的值, 这个函数通常为新申请的内存做初始化工作。
- strcpy,即string copy(字符串复制)的缩写。strcpy是一种C语言的标准库函数,strcpy把含有'\0'结束符的字符串复制到另一个地址空间,返回值的类型为char*。
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
using namespace std;
//2、定义变量的时候一定要初始化,很多的Bug产生都是由于没有初始化造成的
/*
memset:
memset是计算机中C/C++语言初始化函数。
作用是将某一块内存中的内容全部设置为指定的值, 这个函数通常为新申请的内存做初始化工作。
*/
/*
strcpy:
strcpy,即string copy(字符串复制)的缩写。
strcpy是一种C语言的标准库函数,strcpy把含有'\0'结束符的字符串复制到另一个地址空间,返回值的类型为char*。
*/
void allocateSpace(char *p)
{
p =(char *) malloc(100);
memset(p, 0, 100);
strcpy(p, "hellow world!\0");
}
void test02()
{
char *p = NULL;
allocateSpace(p);
printf("p=%s\n", p);
}
int main()
{
//test01();
test02();
system("pause");
return EXIT_SUCCESS;
}
①为什么为空:理解1:因为test02函数中设置了一个char *p是空的,然后传递到了allocateSpace函数中,实参变为形参,此时的形参操作和test02函数中的实参char*p就没有关系了,
①为什么为空:理解2:验证理解1:所以我直接不运行allocateSpace函数了,输出还是空,因此我传递给allocate里面实参后,就和test02里面的char *p没有关系了,
3、测试3(成功-有自己的理解):二次指针
①运行结果:疑问:为什么这个和测试2不一样,输出内容不是空
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
using namespace std;
//测试3:
void allocateSpace02(char **p)
{
char *temp = (char *)malloc(100);
memset(temp, 0, 100);
strcpy(temp, "hellow world!");
*p = temp;
}
void test03()
{
char *p = NULL;
allocateSpace02(&p);
printf("p=%s\n", p);
}
int main()
{
//test01();
//test02();
test03();
system("pause");
return EXIT_SUCCESS;
}
①为什么不为空:理解1:因为test03函数时候将char *p的地址传递给allocateSpace02函数,allocateSpace02函数是对char *p的地址进行操作(别看是二级指针,其实就是对char *p地址的操作),所以只有test03函数生命周期结束后,才会清除char *p
七、操作:五:全局静态区
1、默认外部链接
1、全局区
1、静态全局变量是内部链接
1、内部链接和外部链接有什么区别?
- 1、如果变量是内部链接的话,那么此变量只能在当前文件夹内被访问
- 2、如果变量是外部链接的话,那么此变量可以被其他文件使用
1、全局静态变量和局部静态变量的区别?
- 1、全局静态变量和局部静态变量都存储在静态区,都是在程序运行期间都是合法有效
- 2、局部静态变量符号的可见范围仅限于当前函数内部,全局静态变量可见范围从定义到文件结尾
1、测试1:静态区
void test01()
{
static int c = 30;//静态区
}
1、头文件不要放定义,只能放声明
1、头文件不能参与编译,每一个.c文件,我们叫做一个编译单元;编译器独立编译每一个.c文件
1、静态区:
①局部静态变量
1、(失败-按照课程源码编写也是报错,不知道是什么情况)测试2:
①运行效果+自己代码
#define _CR_SECURE_NO_WARNINGS
#include <stdlib.h>
#include <iostream>
#include <stdio.h>
#include <string.h>
extern int a=10;//默认外部链接
int a = 10;//全局区
//静态全局变量是内部链接
static int b = 20;//静态区
//头文件不能参与编译,每一个.c文件,我们叫做一个编译单元
//编译器独立编译每一个.c文件
void test02()
{
//声明,表示告诉编译器这个符号是存在的,你让我先编译通过,让连接器去找到底这个符号在哪
extern int g_a;
printf("g_a=%d\n", g_a);
}
int main()
{
//test01();
test02();
system("pause");
return EXIT_SUCCESS;
}
①课程源码
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
//extern int a = 10; 默认外部链接
int a = 10; //全局区
//静态全局变量是内部链接
static int b = 20; //静态区
//内部链接和外部链接有什么区别?
//1. 如果变量是内部链接的话,那么此变量只能在当前文件内访问
//2. 如果是变量是外部链接的话,那么此变量可以被其他文件使用
//1. 全局静态变量和局部静态变量都存储在静态区,都是在程序运行期间都是合法有效
//2. 局部静态变量符号的可见范围仅限于当前函数内部,全局静态变量可见范围从定义到文件结尾
//头文件不要放定义,只能放声明
void test01()
{
static int c = 30; //静态区
}
//头文件不参与编译,每一个.c文件,我们叫做一个编译单元
//编译器独立编译每一个.c文件
void test02()
{
//声明,表示告诉编译器这个符号是存在的,你让我先编译通过,让连接器去找到底这个符号在那
extern int g_a;
printf("g_a = %d\n", g_a);
}
int main(){
test02();
system("pause");
return EXIT_SUCCESS;
}