1.关于指针的概念,错误的是:( )
A.指针是变量,用来存放地址
B.指针变量中存的有效地址可以唯一指向内存中的一块区域
C.野指针也可以正常使用
D.局部指针变量不初始化就是野指针
解析:
答案是:C
野指针不可以正常使用。
知识点:
1、指针就是地址,但口语中说的指针通常指的是指针变量。
2、指针变量:指针变量是用来存放地址的,地址是唯一标识一个内存单元的。(我们通过&出变量的起始地址,把地址存放到一个变量中,这个变量就是指针变量)。
3、野指针
(1)概念:野指针就是指针指向的位置是不可知的——就像一条野狗。
(2)野指针成因:
①指针未初始化;
②指针越界访问;
③指针指向的空间释放。
(3)如何规避野指针
①指针初始化(没有明确初始化的指针初始化NULL(本质是0))
②小心指针越界
③指针指向空间释放,及时置NULL
④避免返回局部变量的地址
⑤指针使用前检查有效性
补充:NULL本质是0,在C++可以直接写0,但是C不可以,C要写成NULL
//为什么要写成NULL,变量一旦赋值为NULL你就知道这是一个指针,让你容易识别
//0地址是用户不能使用的,使用的话程序会崩溃。
2.以下系统中,int类型占几个字节,指针占几个字节,操作系统可以使用的最大内存空间是多大( )
A.32位下:4,4,2^32 64位下:8,8,2^64
B.32位下:4,4,不限制 64位下:4,8,不限制
C.32位下:4,4,2^32 64位下:4,8,2^64
D.32位下:4,4,2^32 64位下:4,4,2^64
解析:
答案是:C
①int类型在32位64位平台下都是4字节;
②指针在32位平台是4字节,在64位平台下是8字节;
③操作系统可以使用的内存空间:地址空间的个数32位平台是2^32个,64位平台是2^64个
3.下面代码的结果是:( )
#include <stdio.h> int main() { int arr[] = { 1,2,3,4,5 }; short* p = (short*)arr;//arr是int*类型,将int*强制转换为short* int i = 0; for (i = 0; i < 4; i++) { *(p + i) = 0; } for (i = 0; i < 5; i++) { printf("%d ", arr[i]); } return 0; }
A.1 2 3 4 5
B.0 0 3 4 5
C.0 0 0 0 5
D.1 0 0 0 0
解析:
答案是:B
知识点:
指针的类型:
①指针的解引用:指针的类型决定了,对指针解引用操作时有多大的权限;
②指针+-整数:指针的类型决定指针向前或向后走一步有多大。
指针类型的意义:指针的不同类型,其实提供了不同的视角去观察和访问内存。
图解:
4.下面关于指针运算说法正确的是:( )
A.整形指针+1,向后偏移一个字节
B.指针-指针得到是指针和指针之间的字节个数
C.整形指针解引用操作访问4个字节
D.指针不能比较大小
解析:
答案是:C
A.整形指针+1,向后偏移4个字节
B.指针减指针,指针必须指向同一块内存空间,得到是两个指针之间的元素个数
D.指针能比较大小
知识点:
1.指针的类型:
指针的类型决定了,指针+-整数的步长,指针解引用操作时的权限。 2.指针的运算①指针+-整数:指针的类型决定了指针向前或向后走一步有多大;
②指针-指针:a.前提:两个指针要指向同一块内存空间(数组)
b.指针减指针的绝对值,得到的是两个指针之间的元素个数。
③指针的关系运算(比较指针的大小):
标准规定:允许指向数组元素的指针与指向数组最后一个元素后面的那个内存位置的指针比较,但是不允许与第一个元素之前的那个内存位置的指针进行比较。
5.在小端机器中,下面代码输出的结果是:( )
#include <stdio.h> int main() { int a = 0x11223344; char* pc = (char*)&a; *pc = 0; printf("%x\n", a); return 0; }
A.00223344
B.0
C.11223300
D.112233
解析:
答案是:C
在VS2019是小端,如下内存中的表示:
二、编程题
1.写一个函数打印arr数组的内容,不使用数组下标,使用指针。
arr是一个整形一维数组。
分析:
使用函数打印数组,需要两个参数:
①数组的首元素地址;②数组的元素个数。
#include<stdio.h> void print(int* p, int sz) { //数组元素只能逐个引用,而不能一次引用整个数组(字符串除外) //逐个使用数组中的每一个元素时,通常借助for循环语句 int i = 0; for (i = 0; i < sz; i++) { printf("%d ", *(p + i)); } printf("\n"); } int main() { int arr[] = { 0 ,1 ,2, 3, 4, 5 ,6, 7, 8, 9, 10 }; //计算数组元素个数 int sz = sizeof(arr) / sizeof(arr[0]); //调用函数实现 //打印数组:①知道数组的地址②知道数组的元素个数 print(arr, sz); return 0; }
2.点击链接,做题
分析:
代码1:数组的形式
#include <stdio.h> #include<string.h> //使用数组的方式实现 void reverse(char* str) { //左下标从0开始 int left = 0; //右下标=元素个数-1 int right = strlen(str) - 1; //循环交换--条件:left<right while (left < right) { //交换 char tmp = *(str + left); *(str + left) = *(str + right); *(str + right) = tmp; //循环调整——趋于循环结束的语句 left++; right--; } } int main() { char arr[10000] = { 0 }; //注:scanf默认读取的时候遇到空格就结束 //输入字符串 gets(arr); //调用函数实现 reverse(arr); //输出 puts(arr); return 0; }
代码2:指针的形式
#include <stdio.h> #include<string.h> //使用指针的方式实现 void reverse(char* str) { //左边的起始地址 char* left = str; //右边的地址 char* right = str + strlen(str) - 1; while (left < right)//指针的关系运算 { char tmp = *left; *left = *right; *right = tmp; left++; right--; } } int main() { char arr[10000] = { 0 }; gets(arr); //调用函数实现 reverse(arr); //输出 puts(arr); return 0; }
3.用C语言在屏幕上输出菱形图案:
分析:关键在于找出行数与空格、*之间的关系。
#include<stdio.h> int main() { int line = 0; scanf("%d", &line); //上-line行 int i = 0; for (i = 0; i < line; i++) { //打印一行 //先打印空格 int j = 0; for (j = 0; j < line - 1 - i; j++) { printf(" "); } //再打印* for (j = 0; j < 2 * (i+1) - 1; j++) { printf("*"); } printf("\n"); } //下--line-1行 for (i = 0; i < line - 1; i++) { //打印一行 //先打印空格 int j = 0; for (j = 0; j <= i; j++) { printf(" "); } //再打印* for (j = 0; j < 2 * (line-1-i) - 1; j++) { printf("*"); } printf("\n"); } return 0; }
如输入6,运行结果:
4.求出0~100000之间的所有“水仙花数”并输出。
“水仙花数”是指一个n位数,其各位数字的n次方之和确好等于该数本身,如:153=1^3+5^3+3^3,则153是一个“水仙花数”。
分析:
判断一个数i是否为水仙花数
1.计算出i是几位数——n
2.计算i的十进制的n次方之和,并判断是否等于i本身
补充:水仙花数其实就是自幂数
#include<stdio.h> #include<math.h> int main() { int i = 0; for (i = 0; i <= 100000; i++) { //判断i是否为水仙花数 //1.计算出i是几位数--n(注:使用一个中间变量tmp,防止i被改变) int n = 1;//一个数最小是一位 int tmp = i; while (tmp > 9) { tmp /= 10; n++; } //2.计算i的十进制的n次方之和,并判断是否等于i本身 tmp = i; int sum = 0; while (tmp) { sum += (int)pow(tmp % 10, n);//pow是算次方的函数,返回类型为double tmp /= 10; } if (sum == i) { printf("%d ", i); } } return 0; }
运行结果:
5.求Sn=a+aa+aaa+aaaa+aaaaa的前5项之和,其中a是一个数字,
例如:2+22+222+2222+22222
/* 分析:a=2 k=0 sum=0 k=0*10+2=2 k=2*10+2=22 k=22*10+2=222 k=222*10+2=2222 k=2222*10+2=22222 循环:第i项为k,则i+1项 = k*10+a;sum += k; */ #include<stdio.h> int main() { int a = 0; int n = 5; scanf("%d", &a); //计算 int i = 0; int k = 0; int sum = 0; for (i = 0; i < n; i++) { k = k * 10 + a; sum += k; } //输出 printf("%d\n", sum); return 0; }