program
int main()
{
int a=0xabcd;
char *p=&a;
while(p)
{
if(*p=='c')
{
printf("i got %c\n",*p);
return;
}
p++;
}
}
1)why i got always an answer like "i got c".
2)no matter how many times i execute this program, why i got %c as c.
3)replace c character with any character, no matter ,why we got such a character that what we put in if condition?.
if(*p=='z') or if(*p=='t') or ....
4)can anybody explain what was the reason?
int a=0xabcd on a 32 bit machine will give you 0x0000abcd. If you try to read the contents of this integer as a character, you'll either get 0x00 or 0xcd, depending on endianess. Neither is a printable ASCII character. This doesn't make any sense.
while(p) means "while p points at an address which is not zero". This doesn't make any sense. Because of this, you continue to loop and read random memory cells outside the allocated integer. Anything can happen. If you are lucky, the program will crash.
To sum it up, it appears you don't quite know what you are doing...
1) You get i got c because your program has a pointer p that points on each bytes of 0xabcd in sequence and beyond ! At some point, the pointer will point on the byte 0x63 which is 'c'. Since this is the if condition, the print statement prints the char pointed by p and you see the message i got c.
2) because of the if condition that execute the print statement only if the byte pointed by p is 0x63 thus 'c'. This is why you always see the same message. Note however that it only works if there is a byte with value 0x63 somewhere in memory.
3) You would write it like this to display other characters.
if((*p=='z') || (*p=='t') || ....)
4) see above answers.
Apart from the nice answer by Mr. #Lundin, just to clarify the logic for the print s,
1)why i got always an answer like "i got c".
Because, you wrote the code to do so. Keeping away the programmatic errors, if you check the logic, you wrote the code so that the printf() will only be executed if *p has a value equal to c. So, no wonder, all the time printf() (if encountered) will print
i got c
Next,
2) no matter how many times i execute this program, why i got %c as c.
Correct. Same reason as above.
3)replace c character with any character, no matter ,why we got such a character that what we put in if condition?.
Your printf() will only be executed if the if condition satisfies. So whatever character you'll use in your if condition, printf() will print only that character only.
You don't seem to know what you're doing.
Closest working exaple would look like this:
#include <stdio.h>
int main()
{
int a[2] = {0x0a0b0c0d, 0};
char *p = (char *) a;
while (*p)
{
if (*p == 0x0c)
{
printf("i got c\n");
return 0;
}
p++;
}
}
Or another better solution:
#include <stdio.h>
int main()
{
int a = 0x0a0b0c0d;
for (int i = 0; i < sizeof (int); i++)
{
if(((char *) &a)[i] == 0x0c)
{
printf("i got c\n");
return 0;
}
}
}
Related
The following code works as expected and outputs ABC:
#include <stdio.h>
void printString (char toPrint [100]);
int main()
{
char hello [100];
hello[0] = 'A';
hello[1] = 'B';
hello[2] = 'C';
hello[3] = '\0';
printString(hello);
}
void printString (char toPrint [100])
{
int i = 0;
while (toPrint[i] != '\0')
{
printf("%c", toPrint[i]);
++i;
}
}
But if I remove the line that adds the null-character
hallo[3] = '\0';
I get random output like wBCÇL, ╗BCÄL, ┬BCNL etc.
Why is that so? What I expected is the loop in printString() to run forever because it doesn't run into a '\0', but what happend to 'A', 'B' and 'C'? Why do B and C still show up in the output but A is replaced by some random character?
You declaration of hello leaves it uninitialized and filled with random bytes
int main()
{
char hello [100];
...
}
If you want zero initialized array use
int main()
{
char hello [100] = {0};
...
}
There must have been, by pure chance, the value for \r somewhere in the memory cells following those of my array hello. That's why my character 'A' was overwritten.
On other machines, "ABC" was ouput as expected, followed by random characters.
Initializing the array with 0s, purposely omitted here, of course solves the problem.
edit:
I let the code print out each character in binary and toPrint[5] was indeed 00001101 which is ASCII for \r (carriage return).
When you declare an automatic like char hello [100];, the first thing to understand is that the 100 bytes can contain just about anything. You must assign values to each byte explicitly to do / have something meaningful.
You are terminating you loop when you find the \0 a.k.a the NUL character. Now, if you comment out the instruction which puts the \0 after the character c, your loop runs until you actually find \0.
Your array might contain \0 at some point or it might not. There are chances you might go beyond the 100 bytes still looking for a \0 and invoke undefined behaviour. You also invoke UB when you try to work with an unassigned piece of memory.
I am working on an assignment for school and am having trouble getting the correct output. I am unsure if there is a problem with my loop or a problem with the method of saving values with pointers. When I run the code I end up with something like this:
Output: There are 369224989 underscores and 0 exclamation points in the sentence.
The assignment specifies to use the prototype and the getchar() function to read the input. I feel like since the first value is so high it is an issue with my loop but I have been working on this for two days and haven't seen anything wrong with it (though I could be staring through it at this point).
In addition I get these warnings when I try and compile the program:
characters.c:28: warning: value computed is not used
characters.c:31: warning: value computed is not used
This makes me think that maybe it isn't communicating properly with the main function.
#include<stdio.h>
//this function prototype was required for the assignment
void count(int* num_, int* num_exclamation);
// intended to count the number of _ and ! in a string using pointers
int main()
{
int num_, num_exclamation;
count(&num_, &num_exclamation);
return 0;
}
void count(int* p_num_, int* p_num_exclamation)
{
char ch;
*p_num_ = *p_num_exclamation = 0;
//attempts to scan a string get the first character
printf("Enter a sentence: ");
ch = getchar();
//attempts to loop while incrementing if it is a ! or _
while(ch != '\n')
{
if(ch == '_')
*++p_num_;
if(ch == '!')
*++p_num_exclamation;
ch = getchar();
}
//prints result
printf("Output: There are %d underscores and %d exclamation points
in the sentence.\n", *p_num_, *p_num_exclamation);
}
This is the second time I have really interacted with pointers with the first being the other half of this assignment which is working properly. I am not particularly comfortable with them yet nor aware of all of their nuances. Any advice to get me looking in the right place would be greatly appreciated.
You have Undefined behavior in your code. *++p_num_; increments the pointer first and then it dereferences it. The value of it is not used. And this way, the pointer points to some memory which are not the variables you supposed it to be. Then you dereference it - that location contains indeterminate value and you print it. Accessing some memory which you don't have permisssion to is - UB.
(*p_num_)++
is the one you wanted. This holds for the other variable also - namely p_num_exclamation. Also return value of getchar is int not char - you should use int to hold the value returned by getchar.
char sentence2[10];
strncpy(sentence2, second, sizeof(sentence2)); //shouldn't I specify the sizeof(source) instead of sizeof(destination)?
sentence2[10] = '\0'; //Is this okay since strncpy does not provide the null character.
puts(sentence2);
//////////////////////////////////////////////////////////////
char *pointer = first;
for(int i =0; i < 500; i++) //Why does it crashes without this meaningless loop?!
{
printf("%c", *pointer);
if(*pointer == '\n')
putchar('\n');
pointer++;
}
So here's the problem. When I run the first part of this code, the program crashes.
However, when I add the for loop that just prints garbage values in memory locations, it does not crash but still won't strcpy properly.
Second, when using strncpy, shouldn't I specify the sizeof(source) instead of sizeof(destination) since I'm moving the bytes of the source ?
Third, It makes sense to me to add the the null terminating character after strncpy, since I've read that it doesn't add the null character on its own, but I get a warning that it's a possible out of bounds store from my pelles c IDE.
fourth and most importantly, why doesn't the simply strcpy work ?!?!
////////////////////////////////////////////////////////////////////////////////////
UPDATE:
#include <stdio.h>
#include <string.h>
void main3(void)
{
puts("\n\n-----main3 reporting for duty!------\n");
char *first = "Metal Gear";
char *second = "Suikoden";
printf("strcmp(first, first) = %d\n", strcmp(first, first)); //returns 0 when both strings are identical.
printf("strcmp(first, second) = %d\n", strcmp(first, second)); //returns a negative when the first differenet char is less in first string. (M=77 S=83)
printf("strcmp(second, first) = %d\n", strcmp(second, first)); //returns a positive when the first different char is greater in first string.(M=77 S=83)
char sentence1[10];
strcpy(sentence1, first);
puts(sentence1);
char sentence2[10];
strncpy(sentence2, second, 10); //shouldn't I specify the sizeof(source) instead of sizeof(destination).
sentence2[9] = '\0'; //Is this okay since strncpy does not provide the null character.
puts(sentence2);
char *pointer = first;
for(int i =0; i < 500; i++) //Why does it crashes without this nonsensical loop?!
{
printf("%c", *pointer);
if(*pointer == '\n')
putchar('\n');
pointer++;
}
}
This is how I teach myself to program. I write code and comment all I know about it so that
the next time I need to look up something, I just look at my own code in my files. In this one, I'm trying to learn the string library in c.
char *first = "Metal Gear";
char sentence1[10];
strcpy(sentence1, first);
This doesn't work because first has 11 characters: the ten in the string, plus the null terminator. So you would need char sentence1[11]; or more.
strncpy(sentence2, second, sizeof(sentence2));
//shouldn't I specify the sizeof(source) instead of sizeof(destination)?
No. The third argument to strncpy is supposed to be the size of the destination. The strncpy function will always write exactly that many bytes.
If you want to use strncpy you must also put a null terminator on (and there must be enough space for that terminator), unless you are sure that strlen(second) < sizeof sentence2.
Generally speaking, strncpy is almost never a good idea. If you want to put a null-terminated string into a buffer that might be too small, use snprintf.
This is how I teach myself to program.
Learning C by trial and error is not good. The problem is that if you write bad code, you may never know. It might appear to work , and then fail later on. For example it depends on what lies in memory after sentence1 as to whether your strcpy would step on any other variable's toes or not.
Learning from a book is by far and away the best idea. K&R 2 is a decent starting place if you don't have any other.
If you don't have a book, do look up online documentation for standard functions anyway. You could have learnt all this about strcpy and strncpy by reading their man pages, or their definitions in a C standard draft, etc.
Your problems start from here:
char sentence1[10];
strcpy(sentence1, first);
The number of characters in first, excluding the terminating null character, is 10. The space allocated for sentence1 has to be at least 11 for the program to behave in a predictable way. Since you have already used memory that you are not supposed to use, expecting anything to behave after that is not right.
You can fix this problem by changing
char sentence1[10];
to
char sentence1[N]; // where N > 10.
But then, you have to ask yourself. What are you trying to accomplish by allocating memory on the stack that's on the edge of being wrong? Are you trying to learn how things behave at the boundary of being wrong/right? If the answer to the second question is yes, hopefully you learned from it. If not, I hope you learned how to allocate adequate memory.
this is an array bounds write error. The indices are only 0-9
sentence2[10] = '\0';
it should be
sentence2[9] = '\0';
second, you're protecting the destination from buffer overflow, so specifying its size is appropriate.
EDIT:
Lastly, in this amazingly bad piece of code, which really isn't worth mentioning, is relevant to neither strcpy() nor strncpy(), yet seems to have earned me the disfavor of #nonsensicke, who seems to write very verbose and thoughtful posts... there are the following:
char *pointer = first;
for(int i =0; i < 500; i++)
{
printf("%c", *pointer);
if(*pointer == '\n')
putchar('\n');
pointer++;
}
Your use of int i=0 in the for loop is C99 specific. Depending on your compiler and compiler arguments, it can result in a compilation error.
for(int i =0; i < 500; i++)
better
int i = 0;
...
for(i=0;i<500;i++)
You neglect to check the return code of printf or indicate that you are deliberately ignoring it. I/O can fail after all...
printf("%c", *pointer);
better
int n = 0;
...
n = printf("%c", *pointer);
if(n!=1) { // error! }
or
(void) printf("%c", *pointer);
some folks will get onto you for not using {} with your if statements
if(*pointer == '\n') putchar('\n');
better
if(*pointer == '\n') {
putchar('\n');
}
but wait there's more... you didn't check the return code of putchar()... dang
better
unsigned char c = 0x00;
...
if(*pointer == '\n') {
c = putchar('\n');
if(c!=*pointer) // error
}
and lastly, with this nasty little loop you're basically romping through memory like a Kiwi in a Tulip field and lucky if you hit a newline. Depending on the OS (if you even have an OS), you might actually encounter some type of fault, e.g. outside your process space, maybe outside addressable RAM, etc. There's just not enough info provided to say actually, but it could happen.
My recommendation, beyond the absurdity of actually performing some type of detailed analysis on the rest of that code, would be to just remove it altogether.
Cheers!
#include <stdio.h>
#include <stdlib.h>
main()
{
char *a,*b,*c={0};
int i=0,j=0;
a=(char *)malloc(20*sizeof(char));
b=(char *)malloc(20*sizeof(char));
c=(char *)malloc(20*sizeof(char));
printf("Enter two strings:");
gets(a);
gets(b);
while(a[i]!=NULL)
{
c[i]=a[i];
i++;
}
while(b[j]!=NULL)
{
c[i]=b[j];
i++;
j++;
}
printf("The concated string is %s",c);
}
this is crazy........i spend one whole night it didn't work and then next night it suddenly works perfectly....i'm confused
There are many things wrong with your code.
Not all of them matter if all you care about is getting the code to work.
However, I have tried here to show you different misconceptions that are clear from your code, and show you how to code it better.
You are misunderstanding what NULL means. a NULL pointer doesn't point at anything
Strings are terminated with '\0' which is an ASCII NUL, not the same thing, though both use the value 0.
char* s = "hello";
The above string is actually 6 characters long. 5 bytes for the hello, 1 for the '\0' that is stuck at the end. Incidentally, this means that you can only have strings up to 19 characters long because you need to reserve one byte for the terminal '\0'
char* r = NULL;
The pointer r is pointing at nothing. There is no '\0' there, and if you attempt to look at r[0], you will crash.
As Ooga pointed out, you missed terminating with '\0' which is going to create random errors because your printf will keep going to try to print until the first zero byte it finds. Whether you crash on any particular run is a matter of luck. Zeros are common, so usually you will stop before you crash, but you will probably print out some junk after the string.
Personally, I would rather crash than have the program randomly print out the wrong thing. At least when you crash, you know something is wrong and can fix it.
You also seem to have forgotten to free the memory you malloc.
If you are going to use malloc, you should use free at the end:
int* a = malloc(20);
...
free(a);
You also are only mallocing 20 characters. If you go over that, you will do horrible things in memory. 20 seems too short, you will have only 19 characters plus the null on the end to play with but if you do have 20 characters each in a and b, you would need 40 characters in c.
If this is an assignment to use malloc, then use it, but you should free when you are done. If you don't have to use malloc, this example does not show a reason for using it since you are allocating a small, constant amount of memory.
You are initializing c:
char* c = {0};
In a way that makes no sense.
The {0} is an array with a single zero value. c is pointing to it, but then you immediately point it at something else and never look at your little array again.
You probably mean that C is pointing to nothing at first.
That would be:
char* c = NULL;
but then you are immediately wiping out the null, so why initialize c, but not a and b?
As a general rule, you should not declare values and initialize them later. You can always do something stupid and use them before they are initialized. Instead, initialize as you declared the:
int* a = malloc(20);
int* b = malloc(20);
int* c = malloc(40);
Incidentally, the size of a char is by definition 1, so:
20* sizeof(char)
is the same as 20.
You probably saw an example like:
20 * sizeof(int)
Since sizeof(int) which is not 1 the above does something. Typically sizeof(int) is 4 bytes, so the above would allocate 80 bytes.
gets is unsafe, since it doesn't say how long the buffer is
ALWAYS use fgets instead of gets. (see below).
Many computers have been hacked using this bug (see http://en.wikipedia.org/wiki/Robert_Tappan_Morris)
Still, since malloc is not really needed, in your code, you really should write:
enum { SIZE = 128 };
char a[SIZE];
fgets(a, SIZE, STDIN);
char b[SIZE];
fgets(b, SIZE, STDIN);
char c[SIZE*2];
int i;
int j = 0;
for (i = 0; a[i] != '\0' && i < 127; i++)
c[j++] = a[i];
for (i; b[i] != '\0' && i < 127; i++)
c[j++] = a[i];
c[j] = '\0';
...
Last, I don't know if you are learning C or C++. I will simply point out that this kind of programming is a lot easier in C++ where a lot of the work is done for you. You can first get concatenation done the easy way, then learn all the pointer manipulation which is harder.
#include <string>
#include <iostream>
using namespace std;
int main() {
string a,b,c;
getline(cin, a); // read in a line
getline(cin, b);
c = a + b;
cout << c;
}
Of course, you still need to learn this low-level pointer stuff to be a sophisticated programmer in C++, but if the purpose is just to read in and concatenate lines, C++ makes it a lot easier.
You are not properly null-terminating c. Add this before the printf:
c[i] = '\0';
Leaving out null-termination will seem to work correctly if the char at i happens to be 0, but you need to set it to be sure.
The string c is not being terminated with a null char, this means printf does not know where to stop and will likely segfault your program when it overruns. The reason you may be getting sporadic success is that there is a random chance the malloced area has been pre zeroed when you allocate it, if this is the case it will succeed as a null char is represented as a literal 0 byte.
there are two solutions available to you here, first you could manually terminate the string with a null char as so:
c[i] = '\0';
Second you can use calloc instead of malloc, it guarantees the memory is always pre zeroed.
As a side note you should likely add some length checking to your code to ensure c will not overflow if A and B are both over 10. (or just make c 40 long)
I hope this helps.
OK so basically I'm trying to get a program that transforms a hexadecimal that i enter into its equivalent base 10 value, i'm pretty sure the algorithm is correct, i just cant get it to correctly read what i enter, any help is much appreciated :) And I'm sorry to anyone who thinks this is a really stupid question.
int main()
{
char hexalpha[] = "aAbBcCdDeEfF";
int i, c;
int answer = 0;
c = getchar();
for (i= 0; answer == 0 && hexalpha[i] != "\0"; ++i)
{
if(hexalpha[i]== c)
answer = (10 + (i/2));
}
return answer;
}
You can't compare strings with != , and hexalpha[i] is a char. So you'd want hexalpha[i] != '\0' instead of hexalpha[i] != "\0"
Returning the answer from main() is a bit clumsy, printing out the answer would be easier, so do
printf("Answer: %d\n", answer);
return 0;
You are returning answer, not printing it. Your problem isn't input, it's output. Return passes the value to whatever function called it (or gives an exit status in the case of main).
At the beginning of your code, add the following:
#include <stdio.h>
At the end of main, replace return answer; with:
printf("%i\n", answer);
return 0;
Also, I'd recommend replacing "0" with '0' in the for loop. Your compiler will give you a warning because it should be a char, not a *char.
There doesn't seem anything wrong with your use of getchar. There is however a problem with the second half of your loop-condition: you compare an int (c) with a string ("\0"). You probably mean to use hexalpha[i] != '\0' (note the single-quotes).
Besides that, you don't see the answer because it's never printed. In most shells you can print the return-value of the last program with $? (on Windows it's %errorlevel%), like this:
echo $?
For example, if I run the program like this:
> a.out
b
> echo $?
11
You see that getchar works correctly, but you don't see the output because the shell doesn't usually print the return-value of a program. Alternatively, you can add a printf-statement at the end of your program. This is recommended anyway because the return-value of main is more commonly used to determine whether the program finished successfully, or not.
printf("%i\n", answer);
return 0;
}