知识点

转自

https://blog.csdn.net/qq_37867156/article/details/81837545     关于 0x3f3f3f3f

 https://www.cnblogs.com/qunqun/p/8653806.html     int   long long    unsigned long long 数据范围

https://blog.csdn.net/qq_34637408/article/details/70877953   二维数组做函数参数 及返回值 

https://www.cnblogs.com/shuqingstudy/p/4733307.html   c 语言 memcpy 二维数组的复制

百度百科:左值和右值

时时勤拂拭

一,int   long long    unsigned long long

unsigned   int   0~4294967295   
int   2147483648~2147483647                    10位  2^31-1
unsigned long 0~4294967295
long   2147483648~2147483647
long long的最大值:9223372036854775807      19位  2^63-1
long long的最小值:-9223372036854775808
unsigned long long的最大值:18446744073709551615     20位   2^64-1

__int64的最大值:9223372036854775807
__int64的最小值:-9223372036854775808
unsigned __int64的最大值:18446744073709551615

二,pi 的定义

 const double pi = acos(-1.0);
const double pi = 4.0*atan(1.0);
const double pi = 2*asin(1.0);    //注意定义域

三,无穷大的定义

① 0x3f3f3f3f是一个很有用的数值,它是满足以下两个条件的最大整数。
1、整数的两倍不超过 0x7f7f7f7f,即int能表示的最大正整数。
2、整数的每8位(每个字节)都是相同的。
② ~0U > > 1 
~ 按位求反
u 作为数字后缀 代表 unsigned 类型变量
>> 1右移一位
在32位的情况下,连起来就是 将32位的0取反后 右移一位。
也就是 01111(31个1)
也就是 int 的最大值 2147482347
 
我们在程序设计中经常需要使用 memset(a, val, sizeof (a)) 初始化一个数组a,
该语句把数值 val(0x00~0xFF)填充到数组a 的每个字节上,所以用memset只能赋值出“每8位都相同”的 int。
 
当需要把一个数组中的数值初始化成正无穷时,为了避免加法算术上溢出或者繁琐的判断,
我们经常用 memset(a, 0x3f, sizeof(a)) 给数组赋 0x3f3f3f3f的值来代替。
 
四,free() 的使用
 double * p = (double*)malloc(sizeof(double*));       // 这步错了
 *p = 4;
printf("%lf ", *p);
 free(p);
 p = NULL;
 
虽然 *p 可以打印出来
但当分配的字节与类型不匹配时,无法释放,会报错
 
五,~
1. 所有正整数的按位取反是其本身+1的负数
2. 所有负整数的按位取反是其本身+1的绝对值
3. 零的按位取反是 -1(0在数学界既不是正数也不是负数)
 
六,二维数组
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef int(*R)[3];   // 列数固定
void fun1(int a[][3])
{
    a[1][3] = 666;
}
R fun2(int a[][3])
{
    a[1][3] = 555;
    return a;
}
int main(void)
{
    int b[3][3] = { 0 };
    
    fun1(b);
    printf("%d
", b[1][3]);
    
    memcpy(b, fun2(b), sizeof(fun2(b)));
    printf("%d
", b[1][3]);

    system("pause");
    return 0;
}

 那么问题来了,为什么调用第一个函数之后 main 函数的 数组 b 会变?

其实很简单,其实数组传递的是指针,在函数调用中,它并没有在栈中另开一个数组

而是通过指针引用 mian 函数中的数组。之前完全没有想到。( ´◔ ‸◔`)

七,数组的复制与比较

① memcmp: 三个参数

 
比较内存区域buf1和buf2的前count个字节。
 
#include <string.h>或#include<memory.h>
 
  • 如果返回值 < 0,则表示 str1 小于 str2。
  • 如果返回值 > 0,则表示 str2 小于 str1。
  • 如果返回值 = 0,则表示 str1 等于 str2。 

 ② memcpy void

参数:  (destin,source,n)

  • destin-- 指向用于存储复制内容的目标数组,类型强制转换为 void* 指针。
  • source-- 指向要复制的数据源,类型强制转换为 void* 指针。
  • n-- 要被复制的字节数。
功能: 从 source 所指的内存地址的起始位置开始拷贝 n 个字节到目标 destin 所指的内存地址的起始位置中
返回值:该函数返回一个指向 destin 的指针
 
八,关于 strlen 的一些问题
int main(void)
{
	char p[] = { 'a','b','c' };
	printf("%d
", strlen(p));
	printf("%c
", *(p + 3));

	
	system("pause");
	return 0;
}

  首先,这段代码是可以正常运行的,其中我得到的 strlen(P) 为 15,这里根据大家环境不同,应该有区别

但明明 p 数组长度为 3,怎么没有报错。大家看一下错误的代码:

int main(void)
{
	char p[] = { 'a','b','c' };
	//printf("%d
", strlen(p));
	printf("%c
", *(p + 3));

	system("pause");
	return 0;
}

 没有 strlen 就直接报错 了

我估计是 因为这里没有限制长度,然后 strlen 里面的 循环就扩展了 数组的长度,

但是,下面这个代码却没有问题:

int main(void)
{
	char p[] = { 'a','b','c' };
	printf("%d ", *(p + strlen(p) + 10));
	
	system("pause");
	return 0;
}

 搞不明白  ( ‘-ωก̀ )

 九,缩写

#define mem(a,b) memset(a,b,sizeof(a))

  

十,左值与右值

按字面意思,通俗地说。以赋值符号 = 为界,= 左边的就是左值,= 右边就是右值。 比如:(1) int b = 3;(2) int a = b;第(2)行代码,a为左值,b为右值。
更深一层,可以将 L-value 的 L, 理解成 Location,表示定位,地址。将 R-value 的 R 理解成 Read,表示读取数据。现在的计算机数据放在内存。内存有两个很基本的属性:内存地址和内存里面放的数据。想象完全一样的箱子。每个箱子有个编号,用来区分到底是哪个箱子,箱子里面可以放东西。内存地址相当于箱子的编号,内存的数据,相当于箱子里面放的东西。
变量名编译之后,会映射成内存地址。看看a = b的含义。其实就是 将 "b地址内存里面的数据",放到"a地址内存"中。
 
 
左值右值基本信息
 
C/C++语言中可以放在赋值符号左边的变量,即具有对应的可以由用户访问的存储单元,并且能够由用户去改变其值的量。左值表示存储在计算机内存的对象,而不是常量或计算的结果。或者说左值是代表一个内存地址值,并且通过这个内存地址,就可以对内存进行读并且写(主要是能写)操作;这也就是为什么左值可以被赋值的原因了。相对应的还有右值:当一个符号或者常量放在操作符右边的时候,计算机就读取他们的“右值”,也就是其代表的真实值。简单来说就是,左值相当于地址值,右值相当于数据值。右值指的是引用了一个存储在某个内存地址里的数据。
案例列举
编辑
比如: int ia,ib;
ib=0;
ia=ib;
在这里,首先定义ia,ib。然后对ib赋值,此时计算机取ib的左值,也就是这个符号代表的内存位置即内存地址值,计算机取0的右值,也就是数值0;然后给ia赋值为ib,此时取ib的右值给ia的左值;
所以说,ib的左值、右值是根据他的位置来说的;
这也算是形式语言的一个有意思之处吧。
 
 
左值右值翻译:
L-value中的L指的是Location,表示可寻址。Avalue (computer science)that has an address.
R-value中的R指的是Read,表示可读。in computer science, a value that does not have an address in a computer language.
左值和右值是相对于赋值表达式而言的。左值是能出现在赋值表达式左边的表达式。左值表达式可以分为可读写的左值和只读左值。右值是可以出现在赋值表达式右边的表达式,他可以是不占据内存空间的临时量或字面量,可以是不具有写入权的空间实体。如
int a=3;
const int b=5;
a=b+2; //a是左值,b+2是右值
b=a+2; //错!b是只读的左值但无写入权,不能出现在赋值符号左边
(a=4)+=28; //a=4是左值表达式,28是右值,+=为赋值操作符
34=a+2; //错!34是字面量不能做左值
 
十一,#define 与三目运算符的陷阱
先上一段代码
#define _CRT_SECURE_NO_WARNINGS
#include<stdlib.h>
#include<stdio.h>  
int main(void)
{
#define MAX(x,y) (x>y)?(x):(y)
#define MIN(x,y) (x<y)?(x):(y)
	printf("%d
", MIN(3, 4));
	printf("%d
", MIN(11, MAX(3, 4)));

	system("pause");
}

 这个看着没什么问题,但是一运行第二个结果就错了。为什么会这样呢?

那是因为 #define 只是替换而已 而且 三目运算符 是右结合,即从右向左算的,你连用两个#define,自己一展开就会发现 运算顺序乱了。

解决方法,只要在前面最外面加一个括号就可以了,保证不会和外界的混淆,代码如下:

#define _CRT_SECURE_NO_WARNINGS
#include<stdlib.h>
#include<stdio.h>  
int main(void)
{
#define MAX(x,y) (x>y?x:y)
#define MIN(x,y) (x<y?x:y)
	printf("%d
", MIN(3, 4));
	printf("%d
", MIN(11, MAX(3, 4)));

	system("pause");
}
 
 

========== ========= ======== ======= ====== ===== ==== === == =

Do you think, because I am poor, obscure, plain, and little,I am soulless and heartless? 

You think wrong! 

I have as much soul as you,  and full as much heart!

And if God had gifted me with some beauty and much wealth, I should have made it as hard for you to leave me, as it is now for me to leave you.  

I am not talking to you now through the medium of custom, conventionalities, nor even of mortal flesh; it is my spirit that addresses your spirit,

just as if both had passed through the grave, and we stood at God's feet, equal, -- as we are!        —— —— Jane Eyre

 
 
原文地址:https://www.cnblogs.com/asdfknjhu/p/12357013.html