学习过程中部分c语言疑惑问题的代码验证

所有代码均为曾经学习过程中不清楚不或明白的问题,做的验证,拿出来分享,文章有点长哦
内容涉及(按文章中的先后顺序):argc和argv;const;getmemory;各种数据类型所占用内存大小;pragma和error;sizeof(*p)和sizeof§;sizeof和strlen;void指针;volatile;while(–a)和while(a–);单链表;双链表;猴子吃桃;阶乘;矩阵乘法;类型转换;冒泡选择排序;大小端;数组首地址表示方法;数组作为结构体变量;数组作为结构体成员;数组作为形参;野指针;指针访问二维数组;指针分配动态内存;指针函数与函数指针;指针数组;质数、最小公倍数、最大公约数、闰年;字符串逆序输出;字符串常量与字符数组;

1.argc和argv

//#include "stdafx.h"
//#include "iostream"

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

int main(int argc, char* argv[])
{
   
	int i;

	for (i = 0; i < argc; i++)
	{
   
		//cout << "argument" << i << ": " << argv[i] << endl;
		printf("argv[%d] = %s\n",i,argv[i]);
	}
	//cout << "total argument:" << argc;
	printf("argc = %d\n", argc);

		//return EXIT_SUCCESS;
		return 0;
}
*/

/*
两个参数中第一个参数argc表示在Dos命令行中的输入的程序名和参数个数之和,第二个参数中argv[0]记录的程序名,后面的argv[i]记录的输入参数。
另外argc argv是标识符,可以修改名称。
*/

2.const

/*
#include<stdio.h>
int main(void)
{
	const int a = 12;
	const int* p = &a;
	p++;
 &b;
	t++;
	p = &b;
	q = &b;	p--;
	int const* q = &a;
	int b = 12;
	int* const r = &b;
	r++;
	const int* const t =
	return 0;
}
*/
/*

#include<stdio.h>
int main()
{ const int a = 12;
const int* p = &a; //这个是指向常量的指针, 指针指向
一个常量
p++; //指针可以自加、 自减
p--; //合法
int const* q = &a; //这个和上面的“const int*p=&
a; ”是一个意思
int b = 12;
int* const r = &b; //这个就是常量指针(常指针) , 不
能自加、 自减, 并且要初始化
//r++; //编译出错
const int* const t = &b; //这个就是指向常量的常指
针, 并且要初始化, 用变量初始化
//t++; //编译出错
p = &b; //const指针可以指向const和非const对象
q = &b; //合法
return 0;
}
*/
/*
#include<stdio.h>
int main(void)
{
	int a = 12;
	int b = 13;
//第一种
	//const int* p = &a;	//或者int const*p=&a;		指向常量的指针,指针的地址可以改,但不能对指针内的数据进行改动,因为这时* p  是一个常量,但	指针p	可以改动
	//可以在后面这么写,(1)	p = &b;	(2)	a = 13;	(3)p++;这三种是合法的	不合法的一种为(1)*p=13;
//第二种
	int* const p = &a;		//常量指针,指针p为常量,此时指针p为常量,所指向的地址不能改动,但指针所指地址数据可以改动
	//可以在后面这样写,(1)a=13;	(2)*p=13;这两种都是合法的   不合法的两种为(1)p = &b;	(2)p++;
//第三种
	//const int* const p= &a;		//指向常量的常指针,并且要初始化,用变量初始化,*p   指针p都是只读的,不可改动
	//可以在后面这样写,(1)a=13;这种是合法的,不合法的三种为(1)p = &b;	(2)*p = 13;	(3)p++;
	//a = 13;
	//p = &b;
	//*p = 13;
	//p++;
	printf("%d\n", *p);
}
*/

3.getmemory

//#pragma warning( disable : 4996)

/*
void getmemory(char *p)
   {
  p=(char *) malloc(100);
  strcpy(p,"hello world");
   }
   int main( )
   {
  char *str=NULL;
  getmemory(str);
  printf("%s/n",str);
  free(str);
  return 0;
	}
 程序崩溃,getmemory中的malloc 不能返回动态内存, free()对str操作很危险
77、void GetMemory(char *p)
 {
  p = (char *)malloc(100);
 }
 void Test(void)
 {
  char *str = NULL;
  GetMemory(str);
  strcpy(str, "hello world");
  printf(str);
 }

 请问运行Test函数会有什么样的结果?
 答:程序崩溃。因为GetMemory并不能传递动态内存,Test函数中的 str一直都是 NULL。strcpy(str, "hello world");将使程序崩溃。

 void GetMemory2(char **p, int num)
 {
  *p = (char *)malloc(num);
 }
 void Test(void)
 {
 char *str = NULL;
 GetMemory(&str, 100);
 strcpy(str, "hello");
 printf(str);
 }
 请问运行Test函数会有什么样的结果?
 答:(1)能够输出hello
	 (2)内存泄漏,因为忘记free
78、char *GetMemory(void)
 {
  char p[] = "hello world";
  return p;
 }
 void Test(void)
 {
  char *str = NULL;
  str = GetMemory();
  printf(str);
 }
 请问运行Test函数会有什么样的结果?
 答:可能是乱码。因为GetMemory返回的是指向“栈内存”的指针,该指针的地址不是 NULL,
 但其原先的内容已经被清除,新内容不可知。
 ---------------------------------------
  下面程序运行有什么样的结果?

	char *GetString(void)

	{

	  char array[6];

	  strcpy(array, “hello”);

	  return array;

	}

	void main()

	{

	  char *pstr = NULL;

	  pstr = GetString();

	  printf("%s\n", pstr);

	}

	答对这个问题,脑子里必须有一根弦,那就是栈内存里的内容如“昙花一现”,其有效的生命周期只等于函数周期,访问栈内存的前提条件是在函数运行范围内,函数一旦退出,相应的栈内存立马消散,如同镜花水月,再访问就是野指针的“非法”操作。

	上例中,函数char *GetString返回了指向局部数组array[6]的指针,但array[6]位于栈中,函数的栈内存在其结束后立刻失效,函数退出后再试图通过pstr访问栈内存就成了非法操作。因此,返回指向栈内存的指针这种机制,看似在函数退出后继续访问栈内存留了一个“后门”,实际上是一个隐晦的陷阱。再比较下面例子:
	*/
/*
#define _CRT_SECURE_NO_WARNINGS
#pragma warning( disable : 4996)
#include<stdio.h>
#include<string.h>
#include<malloc.h>


	char *GetString(void)

   {

	  char array[6]="hello";

	  char *p = (char *)malloc(6);

	  strcpy(p, array);

	  return p;

	}

	int main(void)

	{

	  char *str = NULL;

	  str = GetString();

	  printf("%s\n", str);

	  free(str);

	  return 0;
	  

	}
	
	
	这里先把hello字符串从array[]所在的栈内存拷贝到指针p指向的堆内存中,当GetString 函数结束后,array[]栈内存失效了,但指针p所指的堆内存仍有效并保存着”hello”串,函数返回指向堆的指针就没有问题了。如果把直接用指针指向字符串呢:

	char *GetString(void)

	{

	  char *p = "hello";

	  return p;

	}

	void main()

	{

	  char *str = NULL;

	  str = GetString();

	  printf("%s\n", str);

	}

	把原先的数组修改成指针,即 char *str="hello",这样也可行,因为"hello"串位于常量数据区,在子函数结束后依然有效,通过返回的p指针仍然可以读取这块内存。
	 栈本身主要是由编译器静态维护和管理,所以程序中一般情况下应该避免使用指向栈的指针
---------------------------------------------
79、void Test(void)
 {
   char *str = (char *) malloc(100);
  strcpy(str, “hello”);
  free(str);
  if(str != NULL)
  {
	strcpy(str, “world”);
    printf(str);
   }
 }
 请问运行Test函数会有什么样的结果?
 答:篡改动态内存区的内容,后果难以预料,非常危险。因为free(str);之后,str成为野指针,
 if(str != NULL)语句不起作用。
 野指针不是NULL指针,是指向被释放的或者访问受限内存指针。
 造成原因:指针变量没有被初始化任何刚创建的指针不会自动成为NULL;
	 指针被free或delete之后,没有置NULL;
	 指针操作超越了变量的作用范围,比如要返回指向栈内存的指针或引用,因为栈内存在函数结束时会被释放。
*/

4各种数据类型所占用内存大小

/*
#include<stdio.h>
#include<stdlib.h>

int main()
{
	int n = 0;														//整型
	char ch = 0;													//字符
	int arr1[5] = { 0 };											//整型数组
	char arr2[5] = { 0 };											//字符数组
	int* p1 = &n;													//整形指针
	char* p2 = &ch;													//字符指针
	int* p3 = arr1;													//整形指针
	char* p4 = arr2;												//字符指针
	int(*p5)[5] = &arr1;											//整形数组指针
	char(*p6)[5] = &arr2;											//字符数组指针
	int* arr3[5] = { p1 };											//整形指针数组
	char* arr4[5] = { p2 };											//字符型指针数组
	printf("int占%d个字节\n", sizeof(int));
	printf("short占%d个字节\n", sizeof(short));
	printf("char占%d个字节\n", sizeof(char));
	printf("long占%d个字节\n", sizeof(long));
	printf("float占%d个字节\n", sizeof(float));
	printf("long long占%d个字节\n", sizeof(long long));
	printf("double占%d个字节\n", sizeof(double));
	printf("整形变量占%d个字节\n", sizeof(n));
	printf("字符变量占%d个字节\n", sizeof(ch));
	printf("整形数组 int [5] 占%d个字节\n", sizeof(arr1));
	printf("字符数组 char [5] 占%d个字节\n", sizeof(arr2));
	printf("整形指针 int* 占%d个字节\n", sizeof(p1));
	printf("字符指针 char* 占%d个字节\n", sizeof(p2));
	printf("整形数组指针 占%d个字节\n", sizeof(p5));
	printf("字符数组指针 占%d个字节\n", sizeof(p6));
	printf("整形指针数组 占%d个字节\n", sizeof(arr3));				//指针4个字节,数组5个字节4*5=20
	printf("字符指针数组 占%d个字节\n", sizeof(arr4));				//指针4个字节,数组5个字节4*5=20
	printf("指向整形数组的指针 占%d个字节\n", sizeof(p3));
	printf("指向字符数组的指针 占%d个字节\n", sizeof(p4));



	//system("pause");
	return 0;
}
*/
/*
#include<stdio.h>
#include<stdlib.h>

int main()
{
	printf("int占%d个字节\n", sizeof(int));
	printf("short占%d个字节\n", sizeof(short));
	printf("char占%d个字节\n", sizeof(char));
	printf("long占%d个字节\n", sizeof(long));
	printf("float占%d个字节\n", sizeof(float));
	printf("
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值