Why a constant char does not keep its value

Dear All,

I am bit surpised to see that a const char does not keep it’s value. I am passing a char variable in the fourth parameter of the function

inet.httpPOST(host, port_post, path_post, getGPSCoords() , "Result", 1000);

getGPSCoords() return an array (char):

lo=608.474403&la=4613.160156&al=466.355804&ti=20130715174943.000&ve=0.000000

The header of the function is

int InetGSM::httpPOST(const char* server, int port, const char* path, const char* parameters, char* result, int resultlength){
// code
Serial.println(parameters);
}

parameters is a const char but the Serial.print(), inside of the InetGSM function does not display what I show in the above quote. It trunk the value.
More I add Serial.print into the InetGSM function more it trunked.

Here is the full code of InetGSM
I add 6 Serial.print in that function and I show the result

int InetGSM::httpPOST(const char* server, int port, const char* path, const char* parameters, char* result, int resultlength)
{
        Serial.println(F("Starting to send"));
	Serial.println(parameters); // lo=608.474403&la=4613.160156&al=466.355804&ti=20130715174950.3U79

	Serial.println(parameters); // lo=608.474403&la=4613.160156&al=466.355804&ti=20130715174950


  
  boolean connected=false;
  int n_of_at=0;
  char itoaBuffer[8];
  int num_char;
  char end_c[2];
  end_c[0]=0x1a;
  end_c[1]='\0';

  while(n_of_at<3){
	  if(!connectTCP(server, port)){
	  	#ifdef DEBUG_ON
			Serial.println("DB:NOT CONN");
		#endif	
	    	n_of_at++;
	  }
	  else{
		connected=true;
		n_of_at=3;
	}
  }

  if(!connected){
  	Serial.println(F("Not connected"));
  	return 0;
  }
	
	Serial.println(parameters); // display : ^y
	Serial.println(parameters); //display: : ^y


  gsm.SimpleWrite("POST ");
  gsm.SimpleWrite(path);
  gsm.SimpleWrite(" HTTP/1.1\nHost: ");
  gsm.SimpleWrite(server);
  gsm.SimpleWrite("\n");
  gsm.SimpleWrite("User-Agent: Arduino\n");
  gsm.SimpleWrite("Content-Type: application/x-www-form-urlencoded\n");
  gsm.SimpleWrite("Content-Length: ");
  itoa(strlen(parameters),itoaBuffer,10);
  gsm.SimpleWrite(itoaBuffer);
  gsm.SimpleWrite("\n\n");
  gsm.SimpleWrite(parameters);
  gsm.SimpleWrite("\n\n");
  
  gsm.SimpleWrite(end_c);
 
 Serial.println(parameters); // display : ^y
 Serial.println(parameters); /display : ^y
 
  switch(gsm.WaitResp(10000, 10, "SEND OK")){
	case RX_TMOUT_ERR: 
		return 0;
	break;
	case RX_FINISHED_STR_NOT_RECV: 
		return 0; 
	break;
  }

 delay(50);
	#ifdef DEBUG_ON
		Serial.println("DB:SENT");
	#endif	

  int res= gsm.read(result, resultlength);
  Serial.println(F("Data sent"));
  
  //gsm.disconnectTCP();
  return res;
}

Is there any reasons?
Do you need more code?

Note that parameter is not a const char. It is a const char *. The pointer is guaranteed to stay constant, not the objects it points to.

I am bit surpised to see that a const char does not keep it's value. I am passing a char variable in the fourth parameter of the function

What is const about the output from a function? Where is the code for that function? How are we supposed to help you fix that function without seeing it?

All that the const in the function argument's declaration means is that the function will not change the data being pointed to.

KeithRB:
Note that parameter is not a const char. It is a const char *. The pointer is guaranteed to stay constant, not the objects it points to.

Ummm, no.

const char *p;       // the pointer p is not constant, but what it points to is constant
char *const q;       // the pointer q is constant, but what it points to is not constant

In terms of a function parameter, declaring something as const for scalar types, and *const for pointer types is useless in the declaration in the header file, since the function gets a copy of the arguments passed (assuming you are not passing a reference). Now inside the function body, it is useful, in that the compiler will warn you if you attempt to modify the copy of the variable passed.

On the other hand, declaring a pointer as const * means that you are telling the compiler that it can assume that the storage isn’t modified in the function by passing the argument (if the value is a global variable or you took the address of it in other places, the compiler still must assume it can be modified by the call – in C 99, they added restricted to say you promise that no other modifications are possible, but I don’t recall if C++ added restricted, or if it did, if it was in the old release Arduino includes with the IDE.

As usual, you are correct sir... I should have checked my "C PRogramming FAQ" before posting.

KeithRB: As usual, you are correct sir... I should have checked my "C PRogramming FAQ" before posting.

Well, in this case, I was on the ANSI C standards committee when this was added from C++ (I've been working on the GNU compiler since about 1988, and before that had written a C front end for my employer's common compiler toolchain).

It is a common confusion, in that many people think of it like a storage class (auto, static, extern), when instead as a type modifier. However, that is how Bjarne Stroustrup defined it in the then new language C++.

In the middle of the C standards process, the Microsoft C compiler had added const/volatile support (along with the GNU compiler), and one of the other members proposed that we 'fix it and make it more logical' by changing the binding. The fact that his compiler did not yet support it, and his competitor (Microsoft) would have to have an option to change the meaning obviously had nothing to do with the proposal. It got shot down. As I recall, only a few people voted affirmative, almost all were direct competitors to Microsoft.

A function returning a char* immediately raises a red flag in my mind. The naive implementation which returns the address of an automatic local variable is a recipe for disaster, and from the OP's vague description of the problem I suspect this is what they're doing.

PeterH: A function returning a char* immediately raises a red flag in my mind. The naive implementation which returns the address of an automatic local variable is a recipe for disaster, and from the OP's vague description of the problem I suspect this is what they're doing.

Well there are are alternate possibilities that are used in various C codes:

  • The function could be returning a pointer to a static buffer. This isn't safe for reenterant code (either threads or via interrupt), but a lot of Arduino code isn't meant for such environments.
  • The function could be allocating memory via malloc/new, and returning that. This may be a red flag, since the typical Arduino does not have a lot of memory to work with, and you need to handle the case of not having enough memory. In addition, older versions of the library had a bug where you could run out of memory more often.
  • The function could take a char * argument, and returns that value. Here you need to make sure the buffer being passed in is big enough that the function will not accidently clobber adjacent memory.
  • As you mention, a program could be returning the address of a local auto buffer, and this is invalid code. It may appear to work if the called function doesn't do anything else, but you have entered the twilight zone by doing this.

MichaelMeissner:
Well there are are alternate possibilities that are used in various C codes:

I didn’t mean to imply that this will definitely cause a problem, just that it introduces several potential mistakes which could easily trip up a novice programmer.