c语言 指针转换为整数或者 整数转换为指针

简介:

【转】http://blog.csdn.net/deltatang/article/details/41713795


INT36-C. Converting a pointer to integer or integer to pointer

Skip to end of metadata

Go to start of metadata

Although programmers often use integers and pointers interchangeably in C, pointer-to-integer and integer-to-pointer conversions are implementation-defined

Conversions between integers and pointers can have undesired consequences depending on theimplementation. According to the C Standard, subclause 6.3.2.3 [ISO/IEC 9899:2011],

An integer may be converted to any pointer type. Except as previously specified, the result is implementation-defined, might not be correctly aligned, might not point to an entity of the referenced type, and might be a trap representation.

Any pointer type may be converted to an integer type. Except as previously specified, the result is implementation-defined. If the result cannot be represented in the integer type, the behavior is undefined. The result need not be in the range of values of any integer type.

Do not convert an integer type to a pointer type if the resulting pointer is incorrectly aligned, does not point to an entity of the referenced type, or is a trap representation.

Do not convert a pointer type to an integer type if the result cannot be represented in the integer type (seeundefined behavior 24).

The mapping between pointers and integers must be consistent with the addressing structure of the execution environment. Issues may arise, for example, on architectures that have a segmented memory model.

Noncompliant Code Example

The size of a pointer can be greater than the size of an integer, such as in an implementation where pointers are 64 bits and unsigned integers are 32 bits. This code example is noncompliant on such implementations because the result of converting the 64-bit ptr cannot be represented in the 32-bit integer type:

void  f( void ) {
   char  *ptr;
   /* ... */
   unsigned  int  number = (unsigned  int )ptr;
   /* ... */
}

Compliant Solution

Any valid pointer to void can be converted to intptr_t or uintptr_t and back with no change in value (seeINT36-EX2). The C Standard guarantees that a pointer to void may be converted to or from a pointer to any object type and back again and that the result must compare equal to the original pointer. Consequently, converting directly from a char * pointer to a uintptr_t, as in this compliant solution, is allowed on implementations that support the uintptr_t type.

#include <stdint.h>
 
void  f( void ) {
   char  *ptr;
   /* ... */
   uintptr_t  number = ( uintptr_t )ptr; 
   /* ... */
}

Noncompliant Code Example

In this noncompliant code example, the pointer ptr is converted to an integer value. The high-order 9 bits of the number are used to hold a flag value, and the result is converted back into a pointer. This example is noncompliant on an implementation where pointers are 64 bits and unsigned integers are 32 bits because the result of converting the 64-bit ptr cannot be represented in the 32-bit integer type.

void  func(unsigned  int  flag) {
   char  *ptr;
   /* ... */
   unsigned  int  number = (unsigned  int )ptr;
   number = (number & 0x7fffff) | (flag << 23);
   ptr = ( char  *)number;
}

A similar scheme was used in early versions of Emacs, limiting its portability and preventing the ability to edit files larger than 8MB.

Compliant Solution

This compliant solution uses a struct to provide storage for both the pointer and the flag value. This solution is portable to machines of different word sizes, both smaller and larger than 32 bits, working even when pointers cannot be represented in any integer type. 

struct  ptrflag {
   char  *pointer;
   unsigned  int  flag : 9;
} ptrflag;
 
void  func(unsigned  int  flag) {
   char  *ptr;
   /* ... */
   ptrflag.pointer = ptr;
   ptrflag.flag = flag;
}

Noncompliant Code Example

It is sometimes necessary to access memory at a specific location, requiring a literal integer to pointer conversion. In this noncompliant code, a pointer is set directly to an integer constant, where it is unknown whether the result will be as intended:

unsigned  int  *g( void ) {
   unsigned  int  *ptr = 0xdeadbeef;
   /* ... */
   return  ptr;

The result of this assignment is implementation-defined, might not be correctly aligned, might not point to an entity of the referenced type, and might be a trap representation.

Compliant Solution

Adding an explicit cast may help the compiler convert the integer value into a valid pointer. A common technique is to assign the integer to a volatile-qualified object of type intptr_t or uintptr_t and then assign the integer value to the pointer:

unsigned  int  *g( void ) {
   volatile  uintptr_t  iptr = 0xdeadbeef;
   unsigned  int  *ptr = (unsigned  int  *)iptr;
   /* ... */
   return  ptr;
}

Exceptions

INT36-EX1: A null pointer can be converted to an integer; it takes on the value 0. Likewise, the integer value 0 can be converted to a pointer; it becomes the null pointer.

INT36-EX2: Any valid pointer to void can be converted to intptr_t or uintptr_t or their underlying types and back again with no change in value. Use of underlying types instead of intptr_t or uintptr_t is discouraged, however, because it limits portability.

#include <assert.h>
#include <stdint.h>
 
void  h( void ) {
   intptr_t  i = ( intptr_t )( void  *)&i;
   uintptr_t  j = ( uintptr_t )( void  *)&j;
  
   void  *ip = ( void  *)i;
   void  *jp = ( void  *)j;
  
   assert (ip == &i);
   assert (jp == &j);
}

Risk Assessment

Converting from pointer to integer or vice versa results in code that is not portable and may create unexpected pointers to invalid memory locations.

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

INT36-C

Low

Probable

High

P2

L3

Automated Detection

Tool

Version

Checker

Description

Compass/ROSE


Coverity 6.5 POINTER_CONVERSION_LOSES_BITS Fully Implemented

LDRA tool suite

8.5.4

94 S

Fully implemented
PRQA QA-C v8.2 305, 306, 309, 674 Partially implemented

Related Vulnerabilities

Search for vulnerabilities resulting from the violation of this rule on the CERT website.

Related Guidelines

CERT C++ Coding Standard INT11-CPP. Take care when converting from pointer to integer or integer to pointer
ISO/IEC TR 24772:2013 Pointer Casting and Pointer Type Changes [HFC]
ISO/IEC TS 17961:2013 Converting a pointer to integer or integer to pointer [intptrconv]
MITRE CWE CWE-466, Return of Pointer Value Outside of Expected Range
CWE-587, Assignment of a Fixed Address to a Pointer

Bibliography

[ISO/IEC 9899:2011] 6.3.2.3, "Pointers"

















本文转自fatshi51CTO博客,原文链接:http://blog.51cto.com/duallay/1871615 ,如需转载请自行联系原作者





相关文章
|
2月前
|
C语言
【c语言】指针就该这么学(1)
本文详细介绍了C语言中的指针概念及其基本操作。首先通过生活中的例子解释了指针的概念,即内存地址。接着,文章逐步讲解了指针变量的定义、取地址操作符`&`、解引用操作符`*`、指针变量的大小以及不同类型的指针变量的意义。此外,还介绍了`const`修饰符在指针中的应用,指针的运算(包括指针加减整数、指针相减和指针的大小比较),以及野指针的概念和如何规避野指针。最后,通过具体的代码示例帮助读者更好地理解和掌握指针的使用方法。
60 0
|
23天前
|
存储 NoSQL 编译器
【C语言】指针的神秘探险:从入门到精通的奇幻之旅 !
指针是一个变量,它存储另一个变量的内存地址。换句话说,指针“指向”存储在内存中的某个数据。
76 3
【C语言】指针的神秘探险:从入门到精通的奇幻之旅 !
|
23天前
|
存储 编译器 C语言
【C语言】指针大小知多少 ?一场探寻C语言深处的冒险 !
在C语言中,指针的大小(即指针变量占用的内存大小)是由计算机的体系结构(例如32位还是64位)和编译器决定的。
47 9
|
23天前
|
安全 程序员 C语言
【C语言】指针的爱恨纠葛:常量指针vs指向常量的指针
在C语言中,“常量指针”和“指向常量的指针”是两个重要的指针概念。它们在控制指针的行为和数据的可修改性方面发挥着关键作用。理解这两个概念有助于编写更安全、有效的代码。本文将深入探讨这两个概念,包括定义、语法、实际应用、复杂示例、最佳实践以及常见问题。
42 7
|
1月前
|
存储 C语言
C语言如何使用结构体和指针来操作动态分配的内存
在C语言中,通过定义结构体并使用指向该结构体的指针,可以对动态分配的内存进行操作。首先利用 `malloc` 或 `calloc` 分配内存,然后通过指针访问和修改结构体成员,最后用 `free` 释放内存,实现资源的有效管理。
120 13
|
27天前
|
存储 程序员 编译器
C 语言数组与指针的深度剖析与应用
在C语言中,数组与指针是核心概念,二者既独立又紧密相连。数组是在连续内存中存储相同类型数据的结构,而指针则存储内存地址,二者结合可在数据处理、函数传参等方面发挥巨大作用。掌握它们的特性和关系,对于优化程序性能、灵活处理数据结构至关重要。
|
27天前
|
算法 C语言
C语言中的文件操作技巧,涵盖文件的打开与关闭、读取与写入、文件指针移动及注意事项
本文深入讲解了C语言中的文件操作技巧,涵盖文件的打开与关闭、读取与写入、文件指针移动及注意事项,通过实例演示了文件操作的基本流程,帮助读者掌握这一重要技能,提升程序开发能力。
96 3
|
28天前
|
存储 算法 程序员
C 语言指针详解 —— 内存操控的魔法棒
《C 语言指针详解》深入浅出地讲解了指针的概念、使用方法及其在内存操作中的重要作用,被誉为程序员手中的“内存操控魔法棒”。本书适合C语言初学者及希望深化理解指针机制的开发者阅读。
|
1月前
|
存储 C语言 开发者
C 语言指针与内存管理
C语言中的指针与内存管理是编程的核心概念。指针用于存储变量的内存地址,实现数据的间接访问和操作;内存管理涉及动态分配(如malloc、free函数)和释放内存,确保程序高效运行并避免内存泄漏。掌握这两者对于编写高质量的C语言程序至关重要。
55 11
|
27天前
|
程序员 C语言
C语言中的指针既强大又具挑战性,它像一把钥匙,开启程序世界的隐秘之门
C语言中的指针既强大又具挑战性,它像一把钥匙,开启程序世界的隐秘之门。本文深入探讨了指针的基本概念、声明方式、动态内存分配、函数参数传递、指针运算及与数组和函数的关系,强调了正确使用指针的重要性,并鼓励读者通过实践掌握这一关键技能。
36 1