I'm having trouble understanding how c uses puts() to display parts of a message. Two ways which I would consider equivalent do not work the same way with the function. For example
void skippie(char *msg)
{
puts(msg + 6);
}
char *msg = "Don't call me!";
skippie(msg);
This compiles fine, however this does not
void skippie(char *msg)
{
puts(msg[6]);
}
char *msg = "Don't call me!";
skippie(msg);
how does puts() distinguish between the two and only compile for one? The compiler complains that it wants a "const" char but even if I try and use that syntax it fails. Can anyone explain this?
The index operator also dereferences the pointer, so
msg[6] is equivalent to *(msg + 6), not msg + 6.
Furthermore, you cannot pass a const char* to a function, while it expects a char*. i.e., you also have to update the function signature.
msg + 6 is not the same as msg[6].
As per your code, msg+6 is a char *, while msg[6] represents a char.
Quoting from the man page of puts(), the syntax is
int puts(const char *s);
so, the argument of puts() needs to be a const char *, not a char.
Related
Inside a thread, I run this function:
char *r = NetString("ch","aaaaa");
printf("%s",r); printf("%s","\n");
Which calls
char *NetString(char *id, char *data) {
char *result;
result = (char *)malloc(strlen(id)+strlen(data)+2);
strcpy(result, id);
strcat(result, "/");
strcat(result, data);
printf("%s",result); printf("%s","\n");
return (char *)result;
}
In the console, when I compile this warning shows up:
warning: initialization makes pointer from integer without a cast
[enabled by default]: char *r = NetString("ch","aaaaa");
^
If you need the full code (which may be a bit unorganized), here it is:
pastebin
Apparently, this code runs as expected (returns "ch/aaaaa" twice) when not run in a thread, but when I run it in a thread, the string only prints once (that is, in the NetString function). Any help? Thanks a lot.
This code
char *r = NetString("ch","aaaaa");
and this error
warning: initialization makes pointer from integer without a cast
[enabled by default]: char *r = NetString("ch","aaaaa");
^
almost certainly mean:
You are calling NetString() without providing a function prototype, thus it is treated as returning int.
You are running on a 64-bit platform where pointers are 64 bit and int values are 32 bit.
Thus, your char * pointer value from NetString() gets truncated to an int, then assigned to a pointer, where it no longer points to anything useful.
You need to provide a proper prototype with a function declaration:
char *NetString( char *, char * );
in all code that calls NetString(), and the prototype needs to be before any such calls.
The following code is producing a warning:
const char * mystr = "\r\nHello";
void send_str(char * str);
void main(void){
send_str(mystr);
}
void send_str(char * str){
// send it
}
The error is:
Warning [359] C:\main.c; 5.15 illegal conversion between pointer types
pointer to const unsigned char -> pointer to unsigned char
How can I change the code to compile without warnings? The send_str() function also needs to be able to accept non-const strings.
(I am compiling for the PIC16F77 with the Hi-Tech-C compiler)
Thanks
You need to add a cast, since you're passing constant data to a function that says "I might change this":
send_str((char *) mystr); /* cast away the const */
Of course, if the function does decide to change the data that is in reality supposed to be constant (such as a string literal), you will get undefined behavior.
Perhaps I mis-understood you, though. If send_str() never needs to change its input, but might get called with data that is non-constant in the caller's context, then you should just make the argument const since that just say "I won't change this":
void send_str(const char *str);
This can safely be called with both constant and non-constant data:
char modifiable[32] = "hello";
const char *constant = "world";
send_str(modifiable); /* no warning */
send_str(constant); /* no warning */
change the following lines
void send_str(char * str){
// send it
}
TO
void send_str(const char * str){
// send it
}
your compiler is saying that the const char pointer your sending is being converted to char pointer. changing its value in the function send_str may lead to undefined behaviour.(Most of the cases calling and called function wont be written by the same person , someone else may use your code and call it looking at the prototype which is not right.)
I'm learning C today. I've been coding in managed languages (Java, C#, Python, etc.) for some time now. I thought I was understanding the details of pointers, but then I wrote the following code that worked as expected, but generated an 'incompatible pointer type' warning.
void setText(char* output) {
//code to set output to whatever, no problems here.
}
int main(int argc, const char* argv[]) {
char output[10];
setText(&output);
//[EDITED] ...other test code which printf's and further manipulates output.
return 0;
}
So I googled, and ended up changing the line
setText(&output);
to
setText(output);
which got rid of the warning. But now I don't know why the first one was working at all. I was sending the address of an address as far as I can tell (because char* x; is essentially the same as char x[];). What am I misunderstanding and why do both of these work?
The type of output is char [10], which decays to a char * in the context of a function call (which is why the second variant works).
The type of &output is char (*)[10], i.e. a pointer-to-array. This is not the same thing, hence the compiler warning. However, the value of &output (an address) is equivalent to the value of output (once it has decayed to a char *), so the end result is "as expected".
This may sound like pedantry, but there is a fairly important difference. Try the following:
void foo(const char *p)
{
printf("%s\n", p);
}
int main(void)
{
char output[][6] = { "Hello", "world" };
foo(output[0] + 1);
foo(&output[0] + 1);
}
Recommended reading is the C FAQ on arrays and pointers, in particular question 6.3 and 6.12.
I just started to look at C, coming from a java background. I'm having a difficult time wrapping my head around pointers. In theory I feel like I get it but as soon as I try to use them or follow a program that's using them I get lost pretty quickly. I was trying to follow a string concat exercise but it wasnt working so I stripped it down to some basic pointer practice. It complies with a warning conflicting types for strcat function and when I run it, crashes completly.
Thanks for any help
#include <stdio.h>
#include <stdlib.h>
/* strcat: concatenate t to end of s; s must be big enough */
void strcat(char *string, char *attach);
int main(){
char one[10]="test";
char two[10]="co";
char *s;
char *t;
s=one;
t=two;
strcat(s,t);
}
void strcat(char *s, char *t) {
printf("%s",*s);
}
Your printf() should look like this:
printf("%s",s);
The asterisk is unnecessary. The %s format argument means that the argument should be a char*, which is what s is. Prefixing s with * does an extra invalid indirection.
You get the warning about conflicting types because strchr is a standard library routine, which should have this signature:
char * strcat ( char * destination, const char * source );
Yours has a different return type. You should probably rename yours to mystrchr or something else to avoid the conflict with the standard library (you may get linker errors if you use the same name).
Change
printf("%s",*s);
to
printf("%s",s);
The reason for this is printf is expecting a replacement for %s to be a pointer. It will dereference it internally to get the value.
Since you declared s as a char pointer (char *s), the type of s in your function will be just that, a pointer to a char. So you can just pass that pointer directly into printf.
In C, when you dereference a pointer, you get the value pointed to by the pointer. In this case, you get the first character pointed to by s. The correct usage should be:
printf( "%s", s );
BTW, strcat is a standard function that returns a pointer to a character array. Why make your own?
Replacing *s with s won't append strings yet, here is fully working code :
Pay attention to function urstrcat
#include <stdio.h>
#include <stdlib.h>
/* urstrcat: concatenate t to end of s; s must be big enough */
void urstrcat(char *string, char *attach);
int main(){
char one[10]="test";
char two[10]="co";
char *s;
char *t;
s=one;
t=two;
urstrcat(s,t);
return 0;
}
void urstrcat(char *s, char *t) {
printf("%s%s",s,t);
}
pointers are variable which points to address of a variable.
#include "stdio.h"
void main(){
int a,*b;
a=10;
b=&a;
printf("%d",b);
}
in the follwing code you will see a int 'a' and a pointer 'b'.
here b is taken as pointer of an integer and declared by giving'' before it.'' declare that 'b' is an pointer.then you will see "b=&a".this means b is taking address of integer "a" which is keeping value 10 in that particular memory and printf is printing that value.
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char *abc = "abc";
char *new_str;
new_str = getStr(&abc);
printf("%s", abc);
}
char *getStr(char *str)
{
printf(str);
return str;
}
What's wrong with the code above?
A bunch of small things:
You're passing &abc to getStr(). &abc is a pointer to the variable that is holding your string. Its type a pointer to a pointer, and that's incompatible with the char *str argument of getStr().
Your getStr() is defined after it is used. You either need to move its definition to before main() or add a prototype before main().
The type of a string literal like "abc" is const char *. You're defining a variable of type char *, which is dubious (since it would allow you to modify a string literal, which is not allowed).
here is a working version:
#include <stdio.h>
#include <stdlib.h>
char *getStr(char *str);
int main(void)
{
char *abc = "abc";
char *new_str;
new_str = getStr(abc);
//printf("%s", *abc); don't really need this
}
char *getStr(char *str) {
printf("%s", str);
return str;
}
Here's a list of problems with the old one:
No prototype for your function getStr.
You can't do printf(str) you need a "%s" as an additional param.
You need to change: new_str = getStr(&abc) to new_str = getStr(abc)
A C string is a pointer to a character that begins a sequence of characters that end with a null byte. The variable abc perfectly fits this definition.
Also, abc is of type pointer to character. You are passing the address of abc, ie getStr will be receiving the address of a pointer to a character--so getStr's only argument should be of type pointer to pointer to character. The types do not match up.
EDIT: Also, getStr is called before it's declared. Your compiler may allow this, but it's bad practice for many reasons. You should declare it or define it before it is used. If you are using gcc as your compiler, always use
gcc -ansi -Wall -pedantic
Those three flags will conform to ANSI standards, and it would either yell at you for the above issues or not compile.
Your getStr function takes a char *, but that's not what you're passing it - you're passing the address of the pointer, instead of passing it the actual pointer.
Change:
new_str = getStr(&abc);
to:
new_str = getStr(abc);
and I think it'll work.