第二部分:程序代码评价或者找错
有符号整型和无符号整型混合运算时,有符号型自动转换成无符号型,运算的结果是无符号的。
如果参与运算的数据类型不同,会自动转化为同一类再运算,这就是自动转换
自动转换的规则如下:
1.当参与运算的数据的类型不同时,编译系统会自动先将他们转换成同一类型,然后再进行运算。
转换的基本规则是:“按数据长度增加的方向进行转换”,确保精度不变
2.所有的浮点运算都是以双精度进行
CPU在运算时有“字节对齐”的要求,这样的运算速度是最快的。
3.char型和short型数据参与运算时,必须先转换为int型 这也是涉及CPU的运行原理的。
4.有符号整型和无符号整型混合运算时,有符号型要转换成无符号型,运算的结果是无符号型的。
5.整型和浮点型混合运算时,整型先转换成浮点型,运算的结果是浮点型。
6.在赋值运算中,当赋值号两边的数据类型不同时,右边的类型会转换成左边的类型,然后再赋值到左边。如果右边的数据类型长度大于左边,这样他就会丢失数据精度。
写出下面的结果
#include <iostream>
using namespace std;
int main() {
char str1[] = "abc";
char str2[] = "abc";
const char str3[] = "abc";
const char str4[] = "abc";
const char *str5 = "abc";
const char *str6 = "abc";
char *str7 = "abc";
char *str8 = "abc";
cout << (str1 == str2) << endl;
cout << (str3 == str4) << endl;
cout << (str5 == str6) << endl;
cout << (str7 == str8) << endl;
return 0;
}
答案:0 0 1 1;
str1,str2,str3,str4 是数组变量,它们有各自的内存空间;
而 str5,str6,str7,str8 是指针,它们指向相同的常量区域。
sizeof如果用于数组,只能测出静态数组的大小,无法检测动态分配的或外部数组的大小。
使用异或操作
一个数和自身异或为0,异或操作的性质
自反性:a ^ a = 0
,任何数与自己异或结果为0。
交换性:a ^ b = b ^ a
,异或运算是可交换的。
结合性:(a ^ b) ^ c = a ^ (b ^ c)
,异或运算是可结合的。
与零的结合:a ^ 0 = a
,任何数与0异或结果是它本身。
异或操作的应用
1.交换两个数,通过三个异或操作交换’a’和’b’的值而不需要临时变量的参与
2.找唯一出现的数:在一个数组中,所有数都出现两次,只有一个数出现一次,可以使用异或操作找到这个数
3.取反:一个数与’0xFFFFFFFF’异或可以得到它的按位取反结果
对绝对地址0x100000赋值并且想让程序跳转到绝对地址0x100000去执行
(unsigned int*)0x100000 = 1234
跳转到绝对地址去执行
首先要将 0x100000 强制转换成函数指针,即:
(void (*)())0x100000
然后再调用它:
*((void (*)())0x100000)();
用 typedef 可以看得更直观些:
typedef void(*)() voidFuncPtr;
*((voidFuncPtr)0x100000)();
以下有一些代码和相关涉及的知识点,可以进行代码调试并进行相关知识点的补充和深入学习
翻转字符串的常用方式,
需要注意的一些知识点:末尾\0
,strlen和sizeof的区别,malloc和free相关
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if 0 //使用循环遍历的方式将字符串数组的值进行翻转
int main ()
{
char *src = "hello,world";
int len = strlen(src);
char *des = (char*)malloc(len+1);//要为\0 分配一个空间
char *d = des;
char *s = &(src[len-1]); //指向最后一个字符
while(len--)
{
*d++ = *s--;
}
*d = 0;//尾部要加\0
printf("%s\n",des);
free(des);// 使用完,应当释放空间,以免造成内存汇泄露
return 0;
}
#else //使用 二分思想 遍历前一半元素,并和后一半元素进行交换
int main ()
{
char src[] = "hello,world";
int len = strlen(src);
for (int i=0; i<len; i++)
{
int t = src[i];
src[i] = src[len-1-i];
src[len-1-i] = t;
}
printf("%s\n",src);
return 0;
}
#endif
Sizeof相关知识点
#include <iostream>
#include <string.h>
using namespace std;
void UpperCase(char str[])
{
//这里传入的str的一个指针变量
//sizeof()只能计算静态数组的大小
for (int i = 0; i < sizeof(str)/sizeof(str[0]); i++)
if( 'a'<=str[i] && str[i]<='z' )
str[i] -= ('a'-'A' );
cout << sizeof(str)<<endl;//这里的str相当于是一个指针,如果在32位系统中,这里就是4个字节
//如果是在64位系统中,这里就是8个字节
cout << sizeof(str[0]) << endl;
}
int main ()
{
char str[] = "aBcDe";
cout << sizeof(str)<<endl;//这里传入的参数str就是数组,因为前面已经定义了一个数组
cout << sizeof(str[0]) << endl;
cout << "str字符长度为:" << sizeof(str)/sizeof(str[0]) << endl;
UpperCase( str );
cout << str << endl;
return 0;
}
数组和指针
数组的首地址、指针+1的值是如何计算的、
#include <stdio.h>
int main ()
{
int a[5] = {1, 2, 3, 4, 5};
int *ptr = (int *)(&a+1);
printf("%d,%d", *(a+1), *(ptr-1));
return 0;
}
/***解释
*(a+1)就是a[1]
*(ptr-1)就是a[4]
&a+1不是首地址+1,系统会认为加一个a数组的偏移,是偏移了一个数组的大小(本例是5个int)
int *ptr = (int *)(&a + 1);
则ptr实际上就是&(a[5]),也就是a+5
&a 是数组指针,其类型为 int (*)[5];
指针加1要根据指针类型加上一定的值,不同类型的指针+1之后大小不同
a 是长度为 5 的 int 数组指针,所以要加 5*sizeof(int)
所以 ptr 实际是 a[5]
a,&a 的地址是一样的,但意思不一样,a 是数组首地址,也就是 a[0]的地址,&a 是对象(数组)首地址,
a+1 是数组下一元素的地址,即 a[1],&a+1 是下一个对象的地址,即 a[5]
****/
指针传递相关问题
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
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试图分配内存并将指针返回给调用者,但是由于指针是按值传递的,
getmemory中对指针`P`的修改不会影响`main`中的`str`
*
解决办法应该是二级指针,也就是指向指针的指针。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// 使用二级指针来传递指针
void getmemory(char **p) {
*p = (char *)malloc(100);
if (*p != NULL) { // 检查内存是否分配成功
strcpy(*p, "hello world");
}
}
int main() {
char *str = NULL;
getmemory(&str); // 传递指针的地址
if (str != NULL) { // 检查内存是否分配成功
printf("%s\n", str); // 正确的换行符
free(str); // 释放内存
}
return 0;
}
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void g(int**);
int main()
{
int line[10],i;
int *p=line; //p 是地址的地址
for (i=0;i<10;i++)
{
*p=i;
g(&p);//数组对应的值加 1
}
for(i=0;i<10;i++)
printf("%d\n",line[i]);
return 0;
}
void g(int**p)
{
(**p)++;
(*p)++;// 无效
}
结构体存储、处理器模式大小端、位域
#include <iostream>
#include <string.h>
#include <malloc.h>
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
using namespace std;
typedef struct AA
{
int b1:5;
int b2:2;
}AA;
int main()
{
AA aa;
char cc[100];
strcpy(cc,"0123456789abcdefghijklmnopqrstuvwxyz");
memcpy(&aa,cc,sizeof(AA));
cout << aa.b1 <<endl;
cout << aa.b2 <<endl;
return 0;
}
//00110011001100100011000100110000
结构体存储的字节对齐
#include <stdio.h>
#include <stdlib.h>
struct Apple{
char b;
double x;
};
int main()
{
Apple a;
printf("%d\n",sizeof(a));
return 0;
}
标签:知识点,常用,数组,int,易错,char,str,include,指针
From: https://blog.csdn.net/Stay_Hun_forward/article/details/140592528