Return unsigned char array to main function - c

Background: My original main() is:
int main(int argc, char *argv[])
{
unsigned char output[16] = {0x00}; // copied from code
// .... (some steps to calculate output[i])
for (i = 0; i < 16; i++)
{
printf("%02X ", output[i]); // output[i] is an array of 16-byte hex values
}
return 0;
}
The original program (e.g., calculate.c) is run by command line:
./calculate $(echo "this_is_input"|xxd -p)
Now I want to modify main() as a call function only, e.g., named run(). And write a new main() to call run() function.
The input (equivalent to above command line) is hardcoded in new main(). main() will pass the input value to run() function (instead of using above command line).
run(int argc, char *argv[])
{
....
return output[i];
}
then run() returns the same output[i] to main()
int main()
{
input_char = **equivalent to $(echo "this_is_input"|xxd -p)** // how to define?
unsigned char returned_output[16] = {0x00};
returned_output = run(X, input_char);
print(returned_output);
}
Question:
How to present the hex dump value of $(echo "this_is_input"|xxd -p)** in the main()?
How to modify run() and main() in order to return unsigned char array to main()?

How to present the hex dump value of $(echo "this_is_input"|xxd -p)** in the main()?
You can represent it as an array of characters, or for example an array of arrays of characters - tokenised by whitespace. Latter is the representation that the command line arguments are already in argv.
How to modify run() and main() in order to return unsigned char array to main()?
You must declare the return type of the function. It is not possible to return an array directly in C, and it is undesirable to copy arrays around. A typical solution is to let the caller (main) create the array, and let the called function modify the content of the array:
void run(int argc, char *argv[], unsigned char output[16])
main has a problem. It attempts to assign an array. Arrays are not assignable. Given that arrays cannot be returned from functions either, this makes little sense.
This is how to call run that I've suggested:
unsigned char output[16] = {0x00};
run(argc, argv, output);

Related

Interface with variable argument list function, by using function pointers

I am trying to use an interface of another program, where I have to use the following method:
void iterate_over_entries(Table* table, Func_ptr f, ... )
so the function is designed to call on each table entry the function f() which is user-defined.
The function pointer is defined as:
typedef size_t (*Func_ptr) (char* example, va_list args);
So that means that I have to write a function which is of type Func_ptr in order to manipulate the entries of the table?
So lets say for example I want to whatever - set all strings which have a length below a given one to be "a". Is it then, that I have to put the length into this va_list?
size_t my_method(char* example, va_list args) {
int length = va_arg(args, int);
if (strlen(example) < length) strncpy(example, "a\0", 2);
return 1;
}
So If I did everything so far correct, I only need to call the function, but I have no idea how to do that.. Lets say I want that the command line input sets me the length I allow...
int main(int argc, char** argv){
Table* table; //this is set somehow..
int length = atoi(argv[1]);
size_t (*method)(char* example, va_list list);
method = &my_method;
}
So how do I now tell the program to call iterate_over_entries with with my_method, where the length to my input... :S
Just call it:
int main(int argc, char** argv){
Table* table; //this is set somehow..
int length = atoi(argv[1]);
Func_ptr method;
method = &my_method;
iterate_over_entries(table, method, length);
}
There's no need to assign my_method to another variable, you can just pass it directly.
iterate_over_entries(table, my_method, length);

C literals, where are these stored

Consider the following code:
#include <stdio.h>
void f(const char * str) {
str = "java";
}
void main (int argc, char * argv[]) {
const char *str = "erlang";
f(str);
printf("%s\n", str);
}
The output is "erlang" and I don't quite know why..
My current knowledge says that string literals "erlang" and "java" are both stored in the process adress space, within section "constants". And according to this, the fucntion f should change the pointer to point to "java", but this doesn't happen. Could someone please explain what is going on here?
Because function arguments are passed by value in C and modifying arguments in callee won't affece caller's local variables.
Use pointers to modify caller's local variables.
#include <stdio.h>
void f(const char ** str) { /* add * to declare pointer */
*str = "java"; /* add * to access what is pointed */
}
int main (int argc, char * argv[]) { /* use standard signature */
const char *str = "erlang";
f(&str); /* add & to get a pointer pointing at str */
printf("%s\n", str);
}
C has copy by value. When str is passed as an argument to f, it is copied first, and that very copy is actually passed to f. Assigning "java" to that copy doesn't do anything to the original str in main.
Since you are passing the value that means call by value you will see the output as java if you pass the reference like this:
#include <stdio.h>
void f(const char ** str) {
*str = "java";
}
void main (int argc, char * argv[]) {
const char *str = "erlang";
f(&str);
printf("%s\n", str);
}
output:
rabi#rabi-VirtualBox:~/rabi/c$ gcc ptr1.c
rabi#rabi-VirtualBox:~/rabi/c$ ./a.out
java
Function parameters are its local variables. You can imagine the function definition and its call the following way (I changed the name of the parameter from str to s for clearity)
void f(/*const char * s*/) {
const char *s = str;
s = "java";
}
//...
const char *str = "erlang";
f(str);
Any changes of the local variable s does not influence on the original variable str used as the argument. The variable str itself was unchanged.
You should pass arguments by reference if you are going to change them in a function. For example
#include <stdio.h>
void f( const char ** str )
{
*str = "java";
}
int main( void )
{
const char *str = "erlang";
f( &str );
printf( "%s\n", str );
}
The program output is
java
Take into account that according to the C Standard function main shall have return type int.
Could someone please explain what is going on here?
Many good answers all ready yet thought I'd try to perform a detailed walk-though with OP with slightly modified code.
Consider what happens with f("Hello World"). "Hello World" is a string literal. It initializes a char array. When an array is passed to a function or assigned to a pointer, it is converted to the address of the first element of the array. f() receives a copy of the address of 'H' in its str. #1 prints "Hello World". str is re-assigned to the address of 'j'. #2 prints "java". The function ends without affecting "Hello World".
With str = "erlang", str receives the address of the 'e'. #3 prints "erlang". On the function call, the value of main()'s str is copied to the f()'s str. #1 prints "erlang". Like before, str is re-assigned to the address of 'j'. #2 prints "java". The function ends without affecting main()'s str. #4 prints "erlang".
#include <stdio.h>
void f(const char * str) {
printf("f() before str='%s'\n", str); // #1
str = "java";
printf("f() after str='%s'\n", str); // #2
}
int main(void) {
f("Hello World");
puts("");
const char *str = "erlang";
printf("main() before str='%s'\n", str); // #3
f(str);
printf("main() after str='%s'\n", str); // #4
return 0;
}
Output
f() before str='Hello World'
f() after str='java'
main() before str='erlang'
f() before str='erlang'
f() after str='java'
main() after str='erlang'
As to OP's question:
C literals, where are these stored?
The location of a string literal is not defined in C. It might use the "process address space, within section constants", it might not. What is important is that an array is formed and the address of the first character is given in assignment to a const char *. Further detail: writing to this address is undefined behavior (UB), it may "work", fail, seg-fault, etc.
This would be more obvious if you changed the name of the argument for f...
#include <stdio.h>
void f(const char * foo) {
foo = "java";
}
int main (int argc, char * argv[]) {
const char *str = "erlang";
f(str);
printf("%s\n", str);
}
foo is a different variable to str. It has a different name, a different scope, and can contain a different value. The changes to foo won't propagate to str. If you wanted to modify str from within f, you would need to make f look like this:
void f(const char **foo) {
*foo = "java";
}
... and pass a pointer to str to f like so: f(&str);.
Did you happen to notice how I changed void main to int main? There are only two signatures for main entry points (excluding the equivalents) that are guaranteed by the standard to be portable:
int main(void) { /* ... */ }
... and ...
int main(int argc, char *argv[]) { /* ... */ }
Either way, main always returns int (or equivalent). This shouldn't inconvenience you too much, as in C99 (any half-decent compiler that's newer than fifteen years old) and C11 there's this little gem which allows you to omit return 0; from main:
If the return type of the main function is a type compatible with int, a return from the initial call to the main function is equivalent to calling the exit function with the value returned by the main function as its argument;11) reaching the } that terminates the main function returns a value of 0.
So if anything, your code using an int main entry point is not just portable but also one byte shorter than your code using a non-portable void main entry point.

(windows) DevC++ GCC compiler hangs up or prints infinite characters

I am trying to write some C code, and while running the following, my compiler terminates abruptly, after printing 'A'. Why?
//report expected thing
void Expected(char *s){
int i=0;
int n = sizeof(s)/sizeof(s[0]);
while (i< n)
printf ("%c", s[i]);
printf(" expected.\n");
}
int main(int argc, char *argv){
printf("%c",65); //after this compiler hangs and asks for exit abnormally
char *Arr ={'a'};
Expected(Arr);
return 0;
}
Also, if I put
char *Arr ={"a"}; //note the double quotes
then it starts printing out infinite number of 'a's. Why should this happen?
int n = sizeof(s)/sizeof(s[0]);
is not how to get the length of the array of which the pointer passed as the argument points at the first element.
Pass the size of the array if you want to let your function know that.
char *Arr ={'a'};
Is not good because 'a' is a integer and you converted it to a pointer, then the result has too little chance to be a valid pointer.
char *Arr ={"a"};
is OK because it is a valid pointer, but it will be infinite loop because i is not updated in the while loop.
The type of main() function is implementation-defined. You should use standard type unless you have some reason to use special main().
Your code should be like this:
#include <stdio.h>
//report expected thing
void Expected(const char *s, size_t n){ /* add const because the contents of array won't be modified */
size_t i=0; /* use size_t to match type of n */
while (i < n)
printf ("%c", s[i++]); /* update i */
printf(" expected.\n");
}
int main(void){ /* use standard main(). int main(int argc, char **argv) is the another standard type */
printf("%c",65); //after this compiler hangs and asks for exit abnormally
char Arr[] ={'a'}; /* declare an array instead of a pointer */
Expected(Arr, sizeof(Arr)/sizeof(Arr[0]));
return 0;
}
Finally, if it is really not your produced executable but your compiler that is crashing, throw the broken compiler away and get a new one.

C - passing argument 1 of 'send_data' makes pointer from integer without a cast

Im writing uart code for a microcontroller. My code is working fine with passing string("..."), but giving problem when i try to passing the char('.'). Yes, it is i've declared "s" a pointer for string, but there is a chance of passing char value. Is there any possibilities to pass both string and char values in send_data?
#include <stdio.h>
void send_data( char *s)
{
while(*s!='\0')
{
send_dt1(*s);
s++;
}
}
void send_dt1( char in_c)
{
printf("%c",in_c);
}
int main(void)
{
send_data("sample_data"); //fine
send_data('Q'); //warning, no data displaying
return 0; /* terminate the program */
}
Thanks..
As send_data expects s to be a null-terminated string anyway, I would just recommend using a string:
send_data("Q");
Notes:
you should pass a const char* around as long as you don't modify the string at s
send_data('Q'); //warning, no data displaying
Don't pass character to it . It expects a char * .
You can do this -
send_data("Q");
Also you should declare a prototype for function void send_dt1( char in_c) as you make a call to it before it's definition in function void send_data( char *s) .
This will also generate warning.
You can't pass a char to a function that expects a char *.
If you really need to be able to pass both, you'll need another function to accept a char and put it in a string so that send_data can be called:
void send_char_data(char c)
{
char s[2];
s[0] = c;
s[1] = '\0';
send_data(s);
}
....
int main(void)
{
send_data("sample_data");
send_char_data('Q');
return 0;
}

Command line arguments in main

I've written a code that sums up integers brought in from the command line:
#include <stdio.h>
int main(int argc, int* argv[]) {
int i, s=0;
for (i=1;i<argc;i++)
s=s + *argv[i];
printf("Sum: %d\n", s);
return 0;
}
The best part is, it passes the gcc compiling process, but when I actually run it and insert the numbers, the result seems I somehow breached the range of int.
It seems that you are compiling your code in C89 mode in which s is taken as int by default by compiler. s is uninitialized therefore nothing good could be expected. If fact it will invoke undefined behavior.
Note that argv[i] is of char * type (change your main signature) and you need to convert it to int before adding it to s.
The 2nd argument of main should be either of type char** or of type char*[] and not int*[]. So, *argv[i] is of type char. Instead of getting each character, you can get each string(argv[i] which is of type char*) and then extract the number from it and assign it to a variable, say num. This can be done by using the sscanf function:
#include <stdio.h>
int main(int argc, char* argv[]) { //int changed to char here
int i, s=0,num;
for (i=1;i<argc;i++)
if(sscanf(argv[i],"%d",&num)) //if extraction was successful
s=s + num;
printf("Sum: %d\n", s);
return 0;
}
Assuming you have s initialized properly as shown below.
Along with this the prototype of your main() should be as shown below inorder to get the command line arguments.
int main(int argc, char **argv)
{
int s =0;
// Check for argc matches the required number of arguments */
for(i=1;i<argc;i++)
s=s + atoi(argv[i]); /* Use atoi() to convert your string to integer strtol() can also be used */
printf("%d\n",s);
return 0;
}
PS: Using uninitialized variables lead to undefined behvaior

Resources