Impact of the type qualifiers on storage locations

2019-09-13 11:41发布

As mentioned in the title, I am little confused if the type-qualifiers impact the storage location (stack, bss etc..) of the declarator.To describe more I am considering the following declarations.

int main()
{
   const int value=5;
   const char *str= "Constant String";
}
  • In the above code, the default storage-class-specifier is auto.
  • Hence it is assumed that these constants will be allocated in the stack-frame of main when it is created.
  • Generally, the pointers to various memory locations in stack have the freedom to modify the values contained in it.
  • Hence from the above points it is understandable that, either the type-qualifier adds some logic to preserve the constant nature of the element stored (If so what is it?) or the constants are stored in a read-only-portion of memory.Please elaborate on this.

More detailed example

#include <stdio.h>
int main(void)
{
  int val=5;
  int *ptr=&val;
  const int *cptr=ptr;

  *ptr=10;  //Allowed
  //*cptr=10; Not allowed

  //Both ptr and cptr are pointing to same locations. But why the following error?
  //"assignment of read-only location ‘*cptr’"

  printf("ptr: %08X\n",ptr);
  printf("cptr: %08X\n",cptr);
  printf("Value: %d\n",*ptr);
}

In the above example, both cptr and ptr pointing to the same location. But cptr is pointer to a const type qualified integer. While modifying the value of cptr, the compiler throws a error as "assignment of read-only location ‘*cptr’". But I am able to modify the same location with ptr, as in the output below.Please explain

ptr: BFF912D8
cptr: BFF912D8
Value: 10

2条回答
beautiful°
2楼-- · 2019-09-13 11:52

I'm not going into the details of your example, but would like to make some general remarks:

C language semantics are enforced by compiler and hardware only up to a certain degree: it's the responsibility of the programmer to avoid undefined behaviour.

Case in point, it's very possible to modify a const-qualified variable of automatic storage duration (stack allocation) by casting away constness from a pointer without getting a segfault (hardware enforcement) or a compiler error (the cast tells it to shut up because you know what you're doing).

Language constraints however will be violated, and code will break in practice because the optimizer will make assumptions which no longer hold.

Then, there's the misconception that the type of the expression used to access the object is relevant to the definedness of an operation - it is not.

The effective typing rules (C99 6.5 §6) essentially make C a strongly typed language with very unsound type system. The type information (among it mutability) is carried by the object (storage location) itself, irrespective of how the location is accessed.

This makes storing into a const-qualified storage location illegal (undefined behaviour) but technically possible (unsound type system). Arbitrary type punning through pointers falls in the same category of operations which violate language semantics, but aren't enforced and thus can lead to strange bugs, eg under the assumption of strict aliasing.

查看更多
我想做一个坏孩纸
3楼-- · 2019-09-13 12:13

In your first example:

int main()
{
   const int value=5;
   const char *str= "Constant String";
}

Where the variable value and the string literal will be stored is left to the implementation. All that C standard guarantees is that these will stored in read-only memory which may in text segment, stack or anywhere.

In your second case:

 int *ptr=&val;
 const int *cptr=ptr;

When you try to modify *cptr, the compiler doesn't care whether the actual location pointed by cptr is a read-only or writable. All it cares is that the type qualifier const using which it thinks the location pointed to by cptr is read-only.

Another variant:

    const int i = 5;
    p = &i;
   *p = 99;

In this case, the compiler allows modifying a const value through a pointer. But this is undefined behaviour.

查看更多
登录 后发表回答