LinuxQuestions.org
Download your favorite Linux distribution at LQ ISO.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices

Reply
 
Search this Thread
Old 03-11-2008, 01:22 PM   #1
jrtayloriv
Member
 
Registered: Jun 2004
Location: Inland NW, US
Distribution: Ubuntu
Posts: 365
Blog Entries: 1

Rep: Reputation: 44
'Casting away const'ness' in C


I've been scratching my head for a while trying to figure out this bit of code (I've snipped the irrelevant sections), and I think I've finally managed to wrap my head around it, but I had a few questions I wanted to ask. Here it is:
Code:
#define DECL_CONST_CAST_OF(CCTYPE) \
    union { const CCTYPE *__c_ptr; CCTYPE *__ptr; } __ptr_u

#define const_cast(b) (__ptr_u.__c_ptr = (b), __ptr_u.__ptr)


static const opcode_t *
default_unpack(ARGMOD(PackFile_Segment *self), ARGIN(const opcode_t *cursor))
{
    DECL_CONST_CAST_OF(opcode_t);

    self->op_count = PF_fetch_opcode(self->pf, &cursor);
    self->itype    = PF_fetch_opcode(self->pf, &cursor);
    self->id       = PF_fetch_opcode(self->pf, &cursor);
    self->size     = PF_fetch_opcode(self->pf, &cursor);

    if (self->size == 0)
        return cursor;

    self->data  = const_cast(cursor);
    cursor     += self->size;
    return cursor;
}
So, from what I have been able to gather, here is what is happening --

Essentially, the two macros would get expanded to:

Code:
union { 
    const opcode_t *__c_ptr; 
    opcode_t *__ptr; 
} __ptr_u
and

Code:
self->data = (__ptr_u.__c_ptr = cursor, __ptr_u.__ptr)
The second macro would place cursor into the field of the union that was accepting a const opcode *, so everything would be OK w/ the compiler, since the types && qualifiers match. Then ptr_u.__ptr, since it is on the right-hand side of the comma, would be the actual value of the expression, and that is what would go into self->data -- i.e. a regular (non-const) opcode_t * .

But I am having trouble understanding the implications of this. My questions are:

1) Am I correctly understanding this to mean that self->data is a pointer that has read/write access to the memory that cursor is pointing to, so that they point to the same place, but only self->data has permission to write to it?

2) What is happening internally here? Is there some sort of 'permissions flag' that the compiler flips on/off when they cast away the const via this union trick? I used to think that const marked the memory as non-writable somehow, but obviously not, since self->data and cursor both point to the same thing ... so where are these 'permissions' set on?


Thanks,
jrtayloriv

Last edited by jrtayloriv; 03-11-2008 at 02:51 PM. Reason: removed punctuation mistake
 
Old 03-11-2008, 01:27 PM   #2
ta0kira
Senior Member
 
Registered: Sep 2004
Distribution: FreeBSD 9.1, Kubuntu 12.10
Posts: 3,078

Rep: Reputation: Disabled
Absolutely nothing happens internally. It's 100% compile-time error checking. An exception to this would be e.g. trying to write to memory that wasn't allocated on the stack, heap, or static area, such as trying to overwrite the machine code of a loaded function or the data of a string literal.
ta0kira

PS C-casting only has an effect on POD conversions. With pointers, it's merely an acknowledgement to the compiler that, yes, you realize you are doing something that isn't required to happen implicitly.

Last edited by ta0kira; 03-11-2008 at 01:45 PM.
 
Old 03-11-2008, 03:12 PM   #3
jrtayloriv
Member
 
Registered: Jun 2004
Location: Inland NW, US
Distribution: Ubuntu
Posts: 365
Blog Entries: 1

Original Poster
Rep: Reputation: 44
Thank you for your response.

So basically, the reason that someone would do this is to prevent a warning/error from the compiler about trying to put a const opcode_t * into a opcode_t * variable (which is what self->data is), correct?


Thanks,
jrtayloriv
 
Old 03-11-2008, 04:32 PM   #4
ta0kira
Senior Member
 
Registered: Sep 2004
Distribution: FreeBSD 9.1, Kubuntu 12.10
Posts: 3,078

Rep: Reputation: Disabled
It's not so much for the pointer assignment, but so that the assurance is there that the compiler won't let the data be modified via assignment or calling a non-const member function (in C++.) In general, all pointers should be const unless you have a reason to modify its contents or unless a C function requires a non-const pointer. In some cases C++ compilers will behave differently if a reference (a pointer internally, but used like a normal variable) is const, though.
ta0kira
 
  


Reply

Tags
cast, union


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Type Casting in Lisp indienick Programming 2 01-17-2007 11:51 AM
Type Casting problem C EmtYskY Programming 3 12-29-2006 06:01 PM
casting cynthia Programming 6 10-05-2004 03:58 AM
c++, casting, templates kev82 Programming 0 08-24-2004 05:09 PM
C++ Casting bretthoward Programming 1 05-11-2004 01:11 AM


All times are GMT -5. The time now is 01:33 PM.

Main Menu
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration