C/C++ 笔记 (1)

本文介绍了C++中的指针使用,包括指针分配内存、指针自增的字节数、数组指针行为、cout对不同指针类型的处理。还探讨了左值与右值引用的概念,字符串常量与数组名的相似性,以及sizeof和strlen的区别。此外,提到了标准库std::string的特性,类型判断,基于范围的for循环,以及输入处理函数scanf_s的注意事项。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在C++中创建指针时,系统将分配用来存储地址的内存,但不会分配用来存储指针所指向的数据的内存。如下所示代码,*p没有明确的指向,因为系统会将1放在任何一个合适的内存块中。

int *p;
*P=1;

cout<<"Please enter a number";
cin>>p;

此外,在上面的程序中,若p++; 则指针移动四个字节,因为指针p的类型为int,而int在64位系统中占四个字节。
同样,如下是数组指针的例子。p自增,指针移动了八个字节。

 int a[][2] = { 1,2,3,4,10 };
 int(* p)[2] ;
 p = a;
 cout << *p << endl << p << endl<<a<<endl<<&p<<endl<<**p<<endl;
 p++;
 cout << *p << endl << p << endl<<a[1]<<endl<<&p<<endl<<**p;

在这里插入图片描述

对数组名应用取地址运算符&时,得到的是整个数组的地址,尽管从数字上看, 其与数组第一个元素的地址相同。但从概念上来说,二者是不同的。
3.

//创建大小未知的动态数组
int size;
 cin >> size;
 int *a=new int[size];
 delete [] a;     //new和delete要匹配

一般来说,给cout提供一个指针,它将打印地址。但如果指针类型为char*,则cout会输出指针指向的字符串。可以用类型转换来输出地址。此外,"ch=str1;"只是复制了字符串的地址,并未复制字符串。

#include <iostream>
int main()
{
 using namespace std;
 int *a=new int;
 *a = 5;
 char* ch;
 char str1[20] = "string";
 ch = str1;
 cout << a << endl << ch<<endl
      <<(int *)ch<<endl<<(long*)ch<<endl<<(float*)ch; 
 delete  a;     //new和delete要匹配
 return 0;
}

在这里插入图片描述

const char** s;
const char* ss = "memory";
s = &ss;
*s = "computer";
cout <<s<<endl<< (void*)*s <<endl<<*s<< endl << **s<<endl
 <<&ss<<endl<<(void*)ss<<endl<<ss<<endl<<*ss<<endl;

在这里插入图片描述

#include <iostream>
int main()
{
 using namespace std;
 char a = 'a';
 cout << (int)a << endl;
 cout << a++ << endl;
 cout << ++a << endl;
 cout << a + 1 << endl;
 cout<< 1 + a;
return 0;
}

在这里插入图片描述

#include <iostream>
int main()
{
 using namespace std;
 int a = 99;
 //尽量不要这样书写
 cout << a << endl << a++ << endl << ++a << endl << a + 1 << endl << 1 + a; 
 // <<和>>输入输出符号其实是一个输入输出函数重载过后的东西,
 //为了方便使用写成了这样的形式,后面跟着的输出内容其实都是函数的参数,
// 对于不同的编译器,函数参数的求值顺序可能有所不同.
 return 0;
}

在这里插入图片描述
6.右值引用

左值的英文简写为“lvalue”,右值的英文简写为“rvalue”。它们并非分别是"left value"、“right value” 的缩写。
lvalue 是“loactor value”的缩写,可意为存储在内存中、有明确存储地址(可寻址)的数据,而 rvalue 译为 “read value”,指的是那些可读,可以提供数据值的数据(不一定可以寻址,例如存储于寄存器中的数据)。

#include <iostream>
int main()
{
 int x = 1;
 int y = 1;
 int&& r = x + y;
 std::cout << r << std::endl;
 x = 2;
 y = 2;
 std::cout << r << std::endl;
 return 0;
}

在这里插入图片描述
7.字符串常量的行为与数组名相同

#include <iostream>
int main()
{
 using std::cin;
 using std::cout;
 using std::endl;
 const char* a = "abc";
 cout << a << " "<<*a<<endl;
 cout << *("abc") << endl;
 for (int i = 0; i < 3; i++)
  cout << "abc"[i] << endl;
 return 0;
}

在这里插入图片描述
8.int & const

int ad=1,aq=3;
int& const q = ad; 
// const放在&右侧无意义,因为引用声明时必须初始化,
// 并且初始化后不能改变与指向的对象间的绑定关系。
// 引用本身可看做const指针,再用const修饰就无意义。
q = aq;//此语句相当于赋值语句,并不是改变q与ad之间的绑定关系。
  1. sizeof 和 strlen
    strlen计算字符串的长度,读取到第一个’\0‘便停止读取;

sizeof 返回类型以及静态分配的对象、结构或数组所占的空间,返回值跟对象、结构、数组所存储的内容没有关系。
sizeof是操作符,不是函数,如sizeof(double),返回整型数,是一个整型表达式,而不是函数调用。
此外,sizeof无法统计动态分配的内存。例如,sizeof(string类),其结果是固定的,并且随编译器而异。

cout << sizeof("\ta\017bc")<<endl<<strlen("\ta\017bc")<<
  endl<<sizeof("\ta\0b")<<endl<<strlen("\ta\01b")
  <<endl<<strlen("\ta\0b");
  // "\ta\017bc" -> \t a \017 b c \0
  // "\ta\0b" -> \t a \000(VS中显示为此值) b \0
  // "\ta\01b" -> \t a \001 b \0

在这里插入图片描述
10. 优先级:后置运算符>(前置运算符、解除引用运算符,方向为从右到左)
不能将常量写入NULL

 int a[] = { 1,2,3,4,5 };
 int* p = a;
 int* qp = NULL;
 //*qp = *(p + 2); //此语句运行出错,不能将常量写入NULL
 qp = p;
 cout << *qp++ << endl<<*qp<<endl<<a[0];  //结果为 1 2 1
 //cout<< (*qp)++ << endl<<*qp<<endl<<a[0]; // 结果为1 2 2
 //cout<< ++ * qp <<endl<<*qp<<endl<<a[0]; // 结果为2 2 2 
 //cout<<++(*qp) <<endl<<*qp<<endl<<a[0]; // 结果为2 2 2

11.std::string中可以存储多个’\0’字符

 std::string s;
    cout << s << endl << sizeof(s) << endl << s.size() << endl << endl;
    for (int i = 0; i < 5; i++)
    {
        s = s + '\0';
        cout << s << endl << sizeof(s) << endl << s.size() << endl << endl;
    }
    s = s + "computer";
    cout << s << endl << sizeof(s) << endl << s.size();

在这里插入图片描述

  1. 判断两个变量的类型是否相同以及输出变量的类型
 int q;
 int c;
 int(* pp[10])(int* );
 int (*(*p)[10])(int*);
 cout << typeid(q).name() << endl << typeid(pp).name() <<
  endl << typeid(p).name() << endl;
 if (typeid(pp) == typeid(p))
  cout << 1;
 if (typeid(pp) == typeid(q))
  cout << 2;
 if (typeid(q) == typeid(c))
  cout << 3;

在这里插入图片描述
13.基于范围的for循环

 int n;
 cin >> n;
 std::vector<int>aa(n);
 //如果不使用引用,则读入的值只会赋给x,而不会赋给aa,可以通过引用来修改aa的值。
for (int& x : aa)
   cin>> x ;
 for (int x : aa)
  cout << x;
  1. 输出百分号
    C语言输出百分号"%%",不能用“%”或“/%”,C++可以直接输出百分号。
#include <stdio.h>
#include <cstring>
#include <iostream>
using namespace std;
int main()
{
	float* error;
	float a = 8.8;
	error = &a;
	char Error[50];
    sprintf_s(Error, "The error is %f %%", *error);
	for (int i = 0; i < strlen(Error); i++)
		cout << Error[i] << endl;
	cout << "%%" << endl << "\%"<<endl<<"%";
}

在这里插入图片描述
15. scanf_s读入字符

#include <iostream>
int main()
{
 char a;
 char b;
 std::cout<<scanf_s("%c%c", &a,sizeof(a),&b,sizeof(b));
 std::cout << a << " " << b;
}

VS里定义了scanf_s用来代替scanf函数,以此避免scanf不检查边界造成内存泄露。
在使用%c和%s读入字符或字符串时,应在地址参数后附加一个缓冲区边界值。

此外,在读入字符时,空格和换行符都会作为字符读入变量里,因此当输入为“%c%c”时,应该键入类似于“cd”,
而不是“c d”或者
“c
d”

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值