C/C++中未定义行为
生活随笔
收集整理的這篇文章主要介紹了
C/C++中未定义行为
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
C/C++中未定義行為
1、變量類型沒有指定。
2、指定類型的方式與C++混淆了,特別是在.c文件中容易出現這種錯誤。
3、變量指定了類型,但是與使用的變量名不符合,使用的變量名會提示為未定義。
在C++中常見的未定義行為
C++ 標準中有大量的未定義行為,如果在標準中查找 undefined behavior,將會看到幾十條相關內容。如此眾多的未定義行為,無疑給我們帶來了許多麻煩,下面我們將列出一些常見的未定義行為,寫程序時應該盡量避免。
指針相關的常見未定義行為有如下內容:
解引用 nullptr 指針;
解引用一個未初始化的指針;
解引用 new 操作失敗返回的指針;
指針訪問越界(解引用一個超出數組邊界的指針);
解引用一個指向已銷毀對象的指針;
解引用一個指向已銷毀對象的指針,有時候很容易就會犯這個錯誤,例如在函數中返回局部指針地址。 一些簡單的錯誤代碼如下:
#include <iostream>
int * get(int tmp){
? ? return &tmp;
}
int main()
{
? ? int *foo = get(10);
? ? std::cout << *foo << std::endl; // Undefined Behavior;
? ? int arr[] = {1,2,3,4};
? ? std::cout << *(arr+4) << std::endl; // Undefined Behavior;
? ? int *bar=0;
? ? *bar = 2; ? ? ? ? ? ? ? ? ? ? ? // Undefined Behavior;
? ? std::cout << *bar << std::endl;
? ? return 0;
}
#include <iostream>
?
int * get(int tmp){
? ? return &tmp;
}
int main()
{
? ? int *foo = get(10);
? ? std::cout << *foo << std::endl; // Undefined Behavior;
?
? ? int arr[] = {1,2,3,4};
? ? std::cout << *(arr+4) << std::endl; // Undefined Behavior;
?
? ? int *bar=0;
? ? *bar = 2; ? ? ? ? ? ? ? ? ? ? ? // Undefined Behavior;
? ? std::cout << *bar << std::endl;
? ? return 0;
}
其他常見未定義行為如下:
有符號整數溢出(文章開頭的例子);
整數做左移操作時,移動的位數為負數;
整數做移位操作時,移動的位數超出整型占的位數。(int64_t i = 1; i <<= 72);
嘗試修改字符串字面值或者常量的內容;
對自動初始化且沒有賦初值的變量進行操作;(int i; i++; cout << i;)
在有返回值的函數結束時不返回內容;
- A:int i=0;i=(i++);
- B:char *p=”hello”;p[1]=’E’
- C:char *p=”hello”;char ch=*p++
- D:int i=0;printf(“%d%d\n”,i++ i--)
- E:都是未定義行為
- F:都不是未定義行為
D:D 答案有點問題,應為,? int i=0;printf(“%d%d\n”,i++ , i--)
一句話,未定義行為就是運行結果不確定
1、變量類型沒有指定。
2、指定類型的方式與C++混淆了,特別是在.c文件中容易出現這種錯誤。
3、變量指定了類型,但是與使用的變量名不符合,使用的變量名會提示為未定義。
在C++中常見的未定義行為
C++ 標準中有大量的未定義行為,如果在標準中查找 undefined behavior,將會看到幾十條相關內容。如此眾多的未定義行為,無疑給我們帶來了許多麻煩,下面我們將列出一些常見的未定義行為,寫程序時應該盡量避免。
指針相關的常見未定義行為有如下內容:
解引用 nullptr 指針;
解引用一個未初始化的指針;
解引用 new 操作失敗返回的指針;
指針訪問越界(解引用一個超出數組邊界的指針);
解引用一個指向已銷毀對象的指針;
解引用一個指向已銷毀對象的指針,有時候很容易就會犯這個錯誤,例如在函數中返回局部指針地址。 一些簡單的錯誤代碼如下:
#include <iostream>
int * get(int tmp){
? ? return &tmp;
}
int main()
{
? ? int *foo = get(10);
? ? std::cout << *foo << std::endl; // Undefined Behavior;
? ? int arr[] = {1,2,3,4};
? ? std::cout << *(arr+4) << std::endl; // Undefined Behavior;
? ? int *bar=0;
? ? *bar = 2; ? ? ? ? ? ? ? ? ? ? ? // Undefined Behavior;
? ? std::cout << *bar << std::endl;
? ? return 0;
}
#include <iostream>
?
int * get(int tmp){
? ? return &tmp;
}
int main()
{
? ? int *foo = get(10);
? ? std::cout << *foo << std::endl; // Undefined Behavior;
?
? ? int arr[] = {1,2,3,4};
? ? std::cout << *(arr+4) << std::endl; // Undefined Behavior;
?
? ? int *bar=0;
? ? *bar = 2; ? ? ? ? ? ? ? ? ? ? ? // Undefined Behavior;
? ? std::cout << *bar << std::endl;
? ? return 0;
}
其他常見未定義行為如下:
有符號整數溢出(文章開頭的例子);
整數做左移操作時,移動的位數為負數;
整數做移位操作時,移動的位數超出整型占的位數。(int64_t i = 1; i <<= 72);
嘗試修改字符串字面值或者常量的內容;
對自動初始化且沒有賦初值的變量進行操作;(int i; i++; cout << i;)
在有返回值的函數結束時不返回內容;
總結
以上是生活随笔為你收集整理的C/C++中未定义行为的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 深入理解C++重载函数
- 下一篇: 两个线程并发执行以下代码,假设a是全局变