(1) 定义指针char *name,但是没有将指针指向有效的地址空间:
示例:
#define _CRT_SECURE_NO_WARNINGS
#include
int main(void)
{
char *name;
//char *name = NULL;
//char array[100] = {0};
//name = array;
printf("What's your name:");
scanf("%s", name);
printf("Your name is %s\n", name);
return 0;
}
(2) 内存泄漏:如果申请的动态内存没有及时释放会怎样?
示例:(针对丢失内存块地址)
#include
#include
int main()
{
int *ptr;
int num = 123;
ptr = (int *)malloc(sizeof(int));
if (ptr == NULL)
{
printf("分配内存失败!\n");
exit(1);
}
printf("请输入一个整数:");
scanf("%d", ptr);
printf("你输入的整数是:%d\n", *ptr);
ptr = #
printf("你输入的整数是:%d\n", *ptr);
free(ptr); //此处?
return 0;
}
如果,程序中,free(ptr),会报错:
是因为:指针ptr已经指向了局部变量num,用free(ptr),去释放一个局部变量!当然,malloc申请的动态内存的地址丢掉了,也就丢失了内存……
Visual Studio中,后缀为.cpp时,报错;
只需修改为:
char *string1 = "I love FishC.com";
char *string2 = "very much";
修改为:
const char *string1 = "I love FishC.com";
const char *string2 = "very much";
Visual Studio中,后缀为.c时,不会报错
示例代码:
#define _CRT_SECURE_NO_WARNINGS
#include
#include
int global_var1;
int global_var2;
static int file_static_var1;
static int file_static_var2;
void func1(int func1_param1, int func1_param2)
{
static int func1_static_var1;
static int func1_static_var2;
// 输出行参的地址
printf("addr of func1_param1: %010p\n", &func1_param1);
printf("addr of func1_param2: %010p\n", &func1_param2);
// 输出静态局部变量的地址
printf("addr of func1_static_var1: %010p\n", &func1_static_var1);
printf("addr of func1_static_var2: %010p\n", &func1_static_var2);
}
void func2(const int func2_const_param1, const int func2_const_param2)
{
int func2_var1;
int func2_var2;
// 输出const参数的地址
printf("addr of func2_const_param1: %010p\n", &func2_const_param1);
printf("addr of func2_const_param2: %010p\n", &func2_const_param2);
// 输出局部变量的地址
printf("addr of func2_var1: %010p\n", &func2_var1);
printf("addr of func2_var2: %010p\n", &func2_var2);
}
int main(void)
{
char *string1 = "I love FishC.com";
char *string2 = "very much";
// 输出函数的地址
printf("addr of func1: %010p\n", func1);
printf("addr of func2: %010p\n", func2);
// 输出字符串常量的地址
printf("addr of string1: %010p\n", string1);
printf("addr of string2: %010p\n", string2);
// 输出全局变量的地址
printf("addr of global_var1: %010p\n", &global_var1);
printf("addr of global_var2: %010p\n", &global_var2);
// 输出文件内的static变量的地址
printf("addr of file_static_var1: %010p\n", &file_static_var1);
printf("addr of file_static_var2: %010p\n", &file_static_var2);
// 输出函数内局部变量的地址
func1(1, 2);
func2(3, 4);
return 0;
}
(1)源文件后缀为.c时,会报错:
即:将变量声明为寄存器变量,那么就没有办法通过取址运算符获得该变量的地址。
(2)源文件后缀为.cpp时,不会报错:
代码: .c报错,.cpp不会报错;
#include
#include
int main(void)
{
static int *pi = (int *)malloc(sizeof(int));
*pi = 520;
printf("*pi = %d\n", *pi);
return 0;
}
解决办法:
静态分配的变量,都是在编译时刻就决定了地址和初始值的来源
malloc是个运行时刻的函数
上面程序如果编译会报错,这是因为初始化静态变量时不能调用函数。static 声明的变量在程序运行过程中是始终存在的,通常在 main 函数运行之前就完成了初始化过程。*4='q?"KR
,D:NB3H' q2`?Koh9.;(
但 malloc 函数的调用是在 main 函数之后进行的,所以从概念上来说,static 声明的变量不可能通过调用库函数来进行初始化。同样的道理,这个规则对于全局变量来讲也是一样的!Li?Q>8o7Y#
!DUX@9V~ I>f+Ase}Wj`vlgKYa4EJ8
对于静态变量来说,可以通过在后面用一个单独的语句给变量分配内存来避免这个问题:n
……
static int *pi;
pi = (int *)malloc(sizeof(int));
……
大块代码的注释一般用 “/* 代码*/”;其中 ”/*“ 和 “*/”作为一个整体使用,如果分割开,就会报错!
备注:代码的另外一种注释方式为:条件编译!
这个报错字面意思是:定义的变量xxx附近的内存被破坏了!
一般情况下,第一反应就是堆栈溢出、内存访问越界 …没错,这是第一个解决方案
【解决方案】如果提示中的变量是指针类型变量,则大概率的就是数组访问越界,需要反复检查数组下标访问的合法性
如果提示中的变量并不是指针,而是普通局部变量,在检查代码逻辑无误后,此时问题的解决方案如下(具体出错原因不太清楚,我认为是VS编译器的优化问题)
【解决方案】:
方法一:可以将该局部变量设置为全局变量即可
方法二:可以在“ 项目 ---- 属性 ---- 配置属性 ---- C/C++ ---- 代码生成 ---- 基本运行时检查:”设置为默认值,点击应用,确定后即可!
参考链接:https://blog.csdn.net/qq_43746320/article/details/104603363
示例代码:
将结构体变量初始化为0,就可以!
即 struct Book b1 , b2 ; 改为:struct Book b1 = { 0 }, b2 = {0};
#include
struct Date
{
int year;
int month;
int day;
};
struct Book
{
char title[128];
char author[40];
float price;
struct Date date;
char publisher[40];
};
struct Book getInput(struct Book book);
void printBook(struct Book book);
struct Book getInput(struct Book book)
{
printf("请输入书名:");
scanf("%s", book.title);
printf("请输入作者:");
scanf("%s", book.author);
printf("请输入售价:");
scanf("%f", &book.price);
printf("请输入出版日期:");
scanf("%d-%d-%d", &book.date.year, &book.date.month, &book.date.day);
printf("请输入出版社:");
scanf("%s", book.publisher);
return book;
}
void printBook(struct Book book)
{
printf("书名:%s\n", book.title);
printf("作者:%s\n", book.author);
printf("售价:%.2f\n", book.price);
printf("出版日期:%d-%d-%d\n", book.date.year, book.date.month, book.date.day);
printf("出版社:%s\n", book.publisher);
}
int main(void)
{
//struct Book b1 = { 0 }, b2 = {0};
struct Book b1 , b2 ;
printf("请录入第一本书的信息...\n");
b1 = getInput(b1);
putchar('\n');
printf("请录入第二本书的信息...\n");
b2 = getInput(b2);
printf("\n\n录入完毕,现在开始打印验证...\n\n");
printf("打印第一本书的信息...\n");
printBook(b1);
putchar('\n');
printf("打印第二本书的信息...\n");
printBook(b2);
return 0;
}
从上代码可以看出,main中调用子函数,通过值传递,将结构体变量b1 b2传递到子函数;
如果修改子函数代码,通过子函数的结构体指针对main中的b1、b2进行赋值、修改,则不会报错:示例如下:
#include
struct Date
{
int year;
int month;
int day;
};
struct Book
{
char title[128];
char author[40];
float price;
struct Date date;
char publisher[40];
};
void getInput(struct Book *book);
void printBook(struct Book *book);
void getInput(struct Book *book)
{
printf("请输入书名:");
scanf("%s", book->title);
printf("请输入作者:");
scanf("%s", book->author);
printf("请输入售价:");
scanf("%f", &book->price);
printf("请输入出版日期:");
scanf("%d-%d-%d", &book->date.year, &book->date.month, &book->date.day);
printf("请输入出版社:");
scanf("%s", book->publisher);
}
void printBook(struct Book *book)
{
printf("书名:%s\n", book->title);
printf("作者:%s\n", book->author);
printf("售价:%.2f\n", book->price);
printf("出版日期:%d-%d-%d\n", book->date.year, book->date.month, book->date.day);
printf("出版社:%s\n", book->publisher);
}
int main(void)
{
struct Book b1, b2;
printf("请录入第一本书的信息...\n");
getInput(&b1);
putchar('\n');
printf("请录入第二本书的信息...\n");
getInput(&b2);
printf("\n\n录入完毕,现在开始打印验证...\n\n");
printf("打印第一本书的信息...\n");
printBook(&b1);
putchar('\n');
printf("打印第二本书的信息...\n");
printBook(&b2);
return 0;
}
总结:
传递结构体(或其他int 、char等数据类型)变量到子函数中,需要初始化;(结构体变量作为参数传递)
传递指向结构体变量的指针,不需要对数据初始化;
详细解释:C语言关于出现错误代码C2040 间接寻址级别不同的问题
粘贴下来的图: