473,320 Members | 1,580 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,320 software developers and data experts.

Setting a const char * in an **argv

On my platform, I see that if I do following:

Expand|Select|Wrap|Line Numbers
  1. void myFunc( const char *myArg )
  2. {
  3.     char **argv;
  4.  
  5.     argv = &myArg;
  6.  
  7.     createTask( ....., argv, .... );
  8.  
  9. }
Compiler complains that I cannot assing argv to point to &myArg - only if the parameter is defined as 'const'. Without the 'const', it works fine.

I wonder then why the address of "myArg" poses trouble to cast it to char ** if it's a const. Does anybody have a clue?
Aug 6 '08 #1
9 3561
Banfa
9,065 Expert Mod 8TB
const char * is a pointer to constant char (or and array of constant char)

char ** is a pointer to pointer to char

The assignment/cast you have done looses the constness of the data you are pointing to and is therefore illegal for a implicit cast.

Without the const you are not loosing the constness of the data and therefore there is no problem.

The other option is to add a const to you declaration of argv.


You could explicitly cast from const char * to char **, the compiler will do this but it is very bad practice as it removes any type safety that the compiler imposes.

In the worst case someone calling the function might pass data that is actually const, that is unchangeable in hardware, and because argv is not const the code using argv could try to change the data pointed to this would likely result in a hardware exception or fail operation of the program.
Aug 6 '08 #2
You could explicitly cast from const char * to char **,
I'm not trying this, but trying a cast from ptr to const char * to char**. I guess it is what you meant.

I understand from your post that "const char *" means "char pointer to const data" (instead of const pointer to char data, which is what I thought this morning). How could I declare a const char pointer to const char data? And a const pointer to const pointer to const char data? (yes, hard to read). Since I'm pointing "myArg" to a string given by a compile-time macro, I guess that would suit better my case (am I right?).

On the other hand, I can't change the parameters "createTask" is accepting, since it is from an API provided in binary shape (and deals with 99% of the other part of my environment, which is already provided too). Actually, I wonder why they did not made it "const" to "const", or more in general why "argv" as main parameter isn't either: It looks like a dirty hack changing main parameters inside main itself.

Thanks.-
Aug 6 '08 #3
If you are trying to point to a compile time macro it would be better to use true macro's by using the #define pre-compiler tag. Look up #define in google and that will show you how to use the tag. When it comes time to compile you will have to find out how your compiler allows you to assign macros at compile time.

Edward
Aug 7 '08 #4
Oops,

maybe I should have said a #define instead of the more confusing term "compile-time macro". A #define is what I meant by "compile-time macro", and is what I'm actually using.
Aug 8 '08 #5
Banfa
9,065 Expert Mod 8TB
On the other hand, I can't change the parameters "createTask" is accepting, since it is from an API provided in binary shape (and deals with 99% of the other part of my environment, which is already provided too). Actually, I wonder why they did not made it "const" to "const", or more in general why "argv" as main parameter isn't either: It looks like a dirty hack changing main parameters inside main itself.
The reason the argv of main is not const is that it is derviced from the command line of the program. That means the system has to parse the command line and create the array passed as argv from it in memory.

Therefore the system is writing to memory and passing a pointer to that memory to main. By definition then this memory is not const.

I agree changing argv parameters seems like a dirty hack.


Another explanation is that I believe the const keyword did not exist in early versions of C but that future version have maintained backwards compatibility and therefore argv in main has remained without the const keyword.
Aug 8 '08 #6
donbock
2,426 Expert 2GB
On my platform, I see that if I do following:

Expand|Select|Wrap|Line Numbers
  1. void myFunc( const char *myArg )
  2. {
  3.     char **argv;
  4.     argv = &myArg;
  5.     createTask( ....., argv, .... );
  6. }
Compiler complains that I cannot assing argv to point to &myArg - only if the parameter is defined as 'const'. Without the 'const', it works fine.

I wonder then why the address of "myArg" poses trouble to cast it to char ** if it's a const. Does anybody have a clue?
myArg is a pointer to read-only chars. This means that myFunc promises not to change the chars pointed to by myArg.

The prototype for createTask apparently declares argv to be a pointer to a pointer to read/writeable chars. This means that the task being created has permission to overwrite the arguments -- which would violate the promise made by the function prototype for myFunc.

You could cast away the const-ness of myArg, but your program might halt and dump core if the created task goes ahead and tries to overwrite the arguments ... or it might work just fine. It depends on your compiler and precisely how myFunc is called.

I can think of two portable and bullet-proof ways to resolve this.

1. Change the prototype for myFunc to declare myArg as "char *". That is, take away the const-ness of myArg at the source rather than casting it away later. This may create new compiler warnings where myFunc is called. You can resolve those warnings by making analogous changes there.

2. Change myFunc to allocate a block of memory of equal size to that pointed to by myArg. (This could be either a dynamic or static allocation depending on exactly how your program sets the size of that block.) Then copy the block pointed to by myArg into your local block. Finally pass a non-const pointer to that local block to createTask. The created task is then free to overwrite the local copy of the arguments. This is only possible if myFunc knows or can compute the size of the block pointed to by myArg.

In the worst case someone calling the function might pass data that is actually const, that is unchangeable in hardware, and because argv is not const the code using argv could try to change the data pointed to this would likely result in a hardware exception or fail operation of the program.
Write-protected hardware is certainly a good reason to use const, but it isn't the only one; although you're right in that it is the most likely way for casting away const-ness to result in a problem for this program.

One minor comment: the name "argv" is not reserved, but its typical usage is as one of the arguments to main(). That isn't exactly the way you're using it here. You might reduce confusion by renaming this variable to something like taskArgv.

Cheers,
Don
Aug 9 '08 #7
donbock
2,426 Expert 2GB
I understand from your post that "const char *" means "char pointer to const data" (instead of const pointer to char data, which is what I thought this morning). How could I declare a const char pointer to const char data? And a const pointer to const pointer to const char data? (yes, hard to read).
The short answer is that it depends on whether the word const appears before or after the asterisk (*). This answer is so short that it doesn't really help you.

A slightly longer answer is that you should read pointer declarations involving const and volatile from right to left:
Expand|Select|Wrap|Line Numbers
  1. int * const ptr = &someInt;
  2. volatile int * const * whatIsThis;
ptr is a const pointer to an int. You can change *ptr; but you can't change ptr.

whatIsThis is a pointer to a const pointer to a volatile int. You can change whatIsThis; you can change **whatIsThis; but can't change *whatIsThis.

For a really good answer you should use google to find one of the many well-written essays on this topic that are on internet.

Cheers,
Don
Aug 9 '08 #8
donbock
2,426 Expert 2GB
2. Change myFunc to allocate a block of memory of equal size to that pointed to by myArg. (This could be either a dynamic or static allocation depending on exactly how your program sets the size of that block.) Then copy the block pointed to by myArg into your local block. Finally pass a non-const pointer to that local block to createTask. The created task is then free to overwrite the local copy of the arguments. This is only possible if myFunc knows or can compute the size of the block pointed to by myArg.
Sorry, that is possibly a very bad idea. Does the task being created persist after myFunc returns? If so, then the quoted suggestion could easily lead to the argv argument to the created task pointing to freed memory. The result would be disastrous. The quoted suggestion could still be used if you were careful to do it in such a way that the local memory block persisted beyond the end of myFunc. But then you might have to worry about a memory leak.
Cheers,
Don
Aug 9 '08 #9
Well,

First thanks a lot for your suggestions and explanations.

The reason for using const char * was that I was pointing it to a compile-time string (with #define). Compiler did not allow me to do the assignation if I did it to a char *.

So. I looked twice the function the API provides to create a task, which accepts an argv and an argc (this one being int). Instead of passing a string, I passed a number through argc, which suited better my application. At first I did not like this solution since it is a bit of hacking the meaning we know argc and argv should have. Anyaway, I contacted support for the API and told me that there is no process done by my OS with argc and argv, so their values should not keep any relationship.

Your second solution was fine to my case, since after creating the task I wait for it to finnish (it sends a packet, awaits ACK, and joins the thread of myFunc).
Aug 11 '08 #10

Sign in to post your reply or Sign up for a free account.

Similar topics

3
by: Steven T. Hatton | last post by:
Sorry about the big code dump. I tried to get it down to the minimum required to demonstrate the problem. Although this is all done with GNU, I believe the problem I'm having may be more general. ...
10
by: JKop | last post by:
Why isn't: int main(int argc, char* argv) { /* ... */ } as: int main(int argc, const char* argv)
5
by: Brad Moore | last post by:
Hey all, I'm getting the following compiler error from my code. I was wondering if anyone could help me understand the concept behind it (I actually did try and compile this degenerate...
16
by: herbertF | last post by:
Hi guys, In a program (not my own) I encountered the declaration of a constant pointer to an array consisting of two other const pointers to arrays. Not quite sure why they do it so complicated,...
5
by: sugaray | last post by:
I wrote a short code as shown below for experiment purpose, It is successfully compilable, yet I found the piece I wrote even confused myself with the consts and the asterisks, and which brought...
10
by: kevin.hall | last post by:
GCC 3.3 and MSVS 6.0 have no problem converting char* to const char* (not even a warning), but MS's WinCE compiler generated an error complained that this was not possible. MS's WinCE compiler did...
7
by: Eric | last post by:
Hi For this code, int getopt (int argc, char *const argv, const char *opts) what does the "char *const argv" mean? Does it equal to "char **const argv"? Or "char *const *argv"? Which is the...
7
by: Martin | last post by:
When referring to the conforming declaration for main, Lint displays Info 818: Pointer parameter 'argv' (line 3) could be declared as pointing to const Presumably it's saying that the...
35
by: Sean Farrow | last post by:
Hi: What is best and safest way of converting a char* to a const char *? Can I use const_cast? Cheers Sean.
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
1
by: PapaRatzi | last post by:
Hello, I am teaching myself MS Access forms design and Visual Basic. I've created a table to capture a list of Top 30 singles and forms to capture new entries. The final step is a form (unbound)...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
1
by: Defcon1945 | last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work
1
by: Shællîpôpï 09 | last post by:
If u are using a keypad phone, how do u turn on JavaScript, to access features like WhatsApp, Facebook, Instagram....
0
by: af34tf | last post by:
Hi Guys, I have a domain whose name is BytesLimited.com, and I want to sell it. Does anyone know about platforms that allow me to list my domain in auction for free. Thank you
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.