On my platform, I see that if I do following: - void myFunc( const char *myArg )
-
{
-
char **argv;
-
-
argv = &myArg;
-
-
createTask( ....., argv, .... );
-
-
}
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?
9 3621 Banfa 9,065
Recognized Expert Moderator Expert
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.
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.-
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
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.
Banfa 9,065
Recognized Expert Moderator Expert
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.
donbock 2,426
Recognized Expert Top Contributor
On my platform, I see that if I do following: - void myFunc( const char *myArg )
-
{
-
char **argv;
-
argv = &myArg;
-
createTask( ....., argv, .... );
-
}
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
donbock 2,426
Recognized Expert Top Contributor
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: - int * const ptr = &someInt;
-
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
donbock 2,426
Recognized Expert Top Contributor
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
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).
Sign in to post your reply or Sign up for a free account.
Similar topics |
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. Someone on the SuSE
programming mailing list suggested my problem is that I'm trying to execute
a function (I assume he meant the constructor) at compile time. The same
source code compile if I don't try to split it up into separate libraries.
...
|
by: JKop |
last post by:
Why isn't:
int main(int argc, char* argv) { /* ... */ }
as:
int main(int argc, const char* argv)
|
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 example).
int foo(const char* argv) { return 0; }
int main(int argc, char* argv)
{
|
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, but is it legal? Most
compilers accept it, but one doesn't recognize the rhs as a constant.
What are the requirements for the rhs in the declaration of a const
pointer? Is the following program legal C?
int main(int argc, char *argv) {
|
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 up three questions to me:
1) will the casting in line 1 affect the rest of the
declarations ?
2) what's the difference between line 2 and line 3
3) are there any practical purposes of the usage of any
of the three ?
| |
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
allow a conversion from char* to const char** though.
I'm interested in what the standard would say about this. (I don't
have a copy.)
Many thanks,
|
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 const?
Thanks
|
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 definition could be:
int main(int argc, char *const *argv)
Why didn't C89 mandate that?
|
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.
|
by: marktang |
last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look !
Part I. Meaning of...
|
by: Hystou |
last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it.
First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
| |
by: Oralloy |
last post by:
Hello folks,
I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>".
The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed.
This is as boiled down as I can make it.
Here is my compilation command:
g++-12 -std=c++20 -Wnarrowing bit_field.cpp
Here is the code in...
|
by: jinu1996 |
last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth.
The Art of Business Website Design
Your website is...
|
by: Hystou |
last post by:
Overview:
Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
|
by: isladogs |
last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 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 a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules.
He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms.
Adolph will...
|
by: conductexam |
last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one.
At the time of converting from word file to html my equations which are in the word document file was convert into image.
Globals.ThisAddIn.Application.ActiveDocument.Select();...
|
by: adsilva |
last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
| |
by: 6302768590 |
last post by:
Hai team
i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
| |