Changing variable when passing by value - pass-by-reference

I have a main function that declares a double. It then passes it to void Display, which displays the double. The main then passes the double (by value) to a function void Pointers which calls the display function and then changes the value of the double. I then run the display function again from within the main, again passing it the double. But the double has changed to be the new value (that we changed it to in Pointers()) and i don't understand why.
As i understand it, when we pass by value, we are handing the function a copy to work with, and it can do whatever it wants to that copy, but it won't change the original version. If we pass by reference, then we are simply handing the address to the original data.
Since we passed by value, shouldn't it have changed it's own copy and left the original alone?
Code below for reference.
#include <iostream>
#include <cctype>
#include <string>
#include <vector>
#include <iomanip>
#include <windows.h> // for a bigger window
using namespace std;
void Heading()
{
system("cls");
cout << "David Fritz, CO127, 04/9/2013 Assignment 14 (Week 12)";
cout << endl;
cout << endl;
}
void Display(string source, double &value, double* &pointer)
{
cout << "Source: " << source << endl;
cout << "Double Address: " << &value << endl;
cout << "Double Value: " << value << endl;
cout << "Pointer Address: " << &pointer << endl;
cout << "Pointer Value: " << pointer << endl;
cout << "Dereferenced Pointer Value: " << *pointer << endl << endl;
}
void Pointer(double value, double* &pointer)
{
string source = "Method";
Display(source, value, pointer);
value = 7;
*pointer = value;
}
int main()
//2. In the main
// • Call the heading function
// • Create a double and assigns it a value
// • Create a pointer that points to the double
{
MoveWindow(GetConsoleWindow(), 100, 0, 700, 800, TRUE); //moves and resizes window
Heading();
string source = "Main";
double aValue = 4;
double* pointer = &aValue;
Display(source, aValue, pointer);
//system("pause");
Pointer(aValue, pointer);
//system("pause");
Display(source, aValue, pointer);
cout << endl;
cout << "Q: If you pass the double by value to the function, why does the value of the" << endl
<< "double change in the main after you return from the function?" << endl << endl;
cout << "A: I dont know. We passed it its own copy, but it didn't care. I'll figure it out"
}
This is the assignment (which i post because step 5 specifically tells me HOW to pass the double and pointer)
Write a program that creates
1. Create a heading function that displays your name, class number, and date.
2. In the main
• Call the heading function
• Create a double and assigns it a value
• Create a pointer that points to the double
3. Write a Display function that takes a string, a pointer, and a double and uses cout statements to display text describing what you are displaying and then display each in turn:
The location it is being displayed from (called from main or method?)
The double address
The double value
The pointer address
The pointer value (pointers hold addresses, this should be the address of the double)
The dereferenced pointer value (what the pointer is pointing to, the double value)
4. Call the display function from main to display the attributes of the pointer and double.
5. Create a function with a void return type that takes a pointer and a double (pass double by value) from the main. Then display the values of the pointer and double as you did in the main.
• Change the value of the double and then assign the point the value of the double (*pointer = double)
• If ptr is the point name and x is the name for the double then *ptr = x;
6. Back in the main re-display the attributes of the pointer and the double
7. Add a pause.
8. Answer this one question:
• Call the heading function
• Display the following question and its answer.
“If you pass the double by value to the function, why does the value of the double change in the main after you return from the function?”

Pointer() does get its own copy (double value), and changing this doesn't change the value in the main function.
However, you are also passing Pointer() an address (double *pointer), and setting the thing at that address to the value (7) as well, with "*pointer = value;". Because you gave Pointer() the address of aValue (&aValue), it changes in main().
EDIT: So you are right about passing by value not changing the original version, but in this case you have passed both by value and by 'reference' (well, a pointer, which is sort of like a reference), so it changed.
Also some other things:
a) Your indentation is a bit confused (although that could have just been from copying and pasting it in)
b) Passing the pointer by reference (double * &pointer), is unnecessary unless you want to change the value of 'pointer', rather than the value at the address it points to. Probably 'double *pointer' is better.
Cheers

Check this version.
It's complete and a lot better.
#include <iostream>
#include <string>
#include <iomanip>
using namespace std;
void Display(string source, double &value, double* pointer)
{
cout << source << endl;
cout << left << setw(40) << "Original Double Address: " << &value << endl;
cout << left << setw(40) << "Original Double Value: " << value << endl;
cout << left << setw(40) << "Original Pointer Address: " << &pointer << endl;
cout << left << setw(40) << "Original Pointer Value: " << pointer << endl;
cout << left << setw(40) << "Original Dereferenced Pointer Value: " << *pointer << endl << endl;
}
void Pointer(double value, double *pointer)
{
string source = "Pointer Function";
value = 1842;
*pointer = value;
Display(source, value, pointer);
}
void main()
{
cout << "Student Name, CO127, Assignment 14.1" << endl << endl;
string source = "Main";
double aValue = 921;
double* pointer = &aValue;
// Initial Values Displayed
Display(source, aValue, pointer);
// Values after passing to function
Pointer(aValue, pointer);
// Values from main after being modified in function.
Display(source, aValue, pointer);
cout << endl;
cout << "Answer " << endl;
}

Related

Is Swift's handling of CVarArg for String buggy?

While writing a Swift wrapper for a C wrapper of a C++ library, I've stumbled on some weird bugs regarding Swift's CVarArg. The C wrapper I already have uses variadic functions which I converted to functions using va_list as an argument so they could be imported (since Swift cannot import C variadic functions). When passing arguments to such a function, once bridged to Swift, it uses the private _cVarArgEncoding property of types conforming to CVarArg to "encode" the values which are then sent as a pointer to the C function. It seems however that this encoding is faulty for Swift Strings.
To demonstrate, I've created the following package:
Package.swift
// swift-tools-version:5.2
import PackageDescription
let package = Package(
name: "CVarArgTest",
products: [
.executable(
name: "CVarArgTest",
targets: ["CVarArgTest"]),
],
targets: [
.target(
name: "CLib"),
.target(
name: "CVarArgTest",
dependencies: ["CLib"])
]
)
CLib
CTest.h
#ifndef CTest_h
#define CTest_h
#include <stdio.h>
/// Prints out the strings provided in args
/// #param num The number of strings in `args`
/// #param args A `va_list` of strings
void test_va_arg_str(int num, va_list args);
/// Prints out the integers provided in args
/// #param num The number of integers in `args`
/// #param args A `va_list` of integers
void test_va_arg_int(int num, va_list args);
/// Just prints the string
/// #param str The string
void test_str_print(const char * str);
#endif /* CTest_h */
CTest.c
#include "CTest.h"
#include <stdarg.h>
void test_va_arg_str(int num, va_list args)
{
printf("Printing %i strings...\n", num);
for (int i = 0; i < num; i++) {
const char * str = va_arg(args, const char *);
puts(str);
}
}
void test_va_arg_int(int num, va_list args)
{
printf("Printing %i integers...\n", num);
for (int i = 0; i < num; i++) {
int foo = va_arg(args, int);
printf("%i\n", foo);
}
}
void test_str_print(const char * str)
{
puts(str);
}
main.swift
import Foundation
import CLib
// The literal String is perfectly bridged to the CChar pointer expected by the function
test_str_print("Hello, World!")
// Prints the integers as expected
let argsInt: [CVarArg] = [123, 456, 789]
withVaList(argsInt) { listPtr in
test_va_arg_int(Int32(argsInt.count), listPtr)
}
// ERROR: Thread 1: EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
let argsStr: [CVarArg] = ["Test", "Testing", "The test"]
withVaList(argsStr) { listPtr in
test_va_arg_str(Int32(argsStr.count), listPtr)
}
The package is available here as well.
As commented in the code above, printing a String via C or a va_list containing Ints works as expected, but when converted to const char *, there's an exception (EXC_BAD_ACCESS (code=EXC_I386_GPFLT)).
So, in short: did I mess up the C side of it or is Swift doing something wrong here? I've tested this in Xcode 11.5 and 12.0b2. If it's a bug, I'll be happy to report it.
This one's a bit tricky: your string is actually being bridged to an Objective-C NSString * rather than a C char *:
(lldb) p str
(const char *) $0 = 0x3cbe9f4c5d32b745 ""
(lldb) p (id)str
(NSTaggedPointerString *) $1 = 0x3cbe9f4c5d32b745 #"Test"
(If you're wondering why it's an NSTaggedPointerString rather than just an NSString, this article is a great read -- in short, the string is short enough to be stored directly in the bytes of the pointer variable rather than in an object on the heap.
Looking at the source code for withVaList, we see that a type's va_list representation is determined by its implementation of the _cVarArgEncoding property of the CVarArg protocol. The standard library has some implementations of this protocol for some basic integer and pointer types, but there's nothing for String here. So who's converting our string to an NSString?
Searching around the Swift repo on GitHub, we find that Foundation is the culprit:
//===----------------------------------------------------------------------===//
// CVarArg for bridged types
//===----------------------------------------------------------------------===//
extension CVarArg where Self: _ObjectiveCBridgeable {
/// Default implementation for bridgeable types.
public var _cVarArgEncoding: [Int] {
let object = self._bridgeToObjectiveC()
_autorelease(object)
return _encodeBitsAsWords(object)
}
}
In plain English: any object which can be bridged to Objective-C is encoded as a vararg by converting to an Objective-C object and encoding a pointer to that object. C varargs are not type-safe, so your test_va_arg_str just assumes it's a char* and passes it to puts, which crashes.
So is this a bug? I don't think so -- I suppose this behavior is probably intentional for compatibility with functions like NSLog that are more commonly used with Objective-C objects than C ones. However, it's certainly a surprising pitfall, and it's probably one of the reasons why Swift doesn't like to let you call C variadic functions.
You'll want to work around this by manually converting your strings to C-strings. This can get a bit ugly if you have an array of strings that you want to convert without making unnecessary copies, but here's a function that should be able to do it.
extension Collection where Element == String {
/// Converts an array of strings to an array of C strings, without copying.
func withCStrings<R>(_ body: ([UnsafePointer<CChar>]) throws -> R) rethrows -> R {
return try withCStrings(head: [], body: body)
}
// Recursively call withCString on each of the strings.
private func withCStrings<R>(head: [UnsafePointer<CChar>],
body: ([UnsafePointer<CChar>]) throws -> R) rethrows -> R {
if let next = self.first {
// Get a C string, add it to the result array, and recurse on the remainder of the collection
return try next.withCString { cString in
var head = head
head.append(cString)
return try dropFirst().withCStrings(head: head, body: body)
}
} else {
// Base case: no more strings; call the body closure with the array we've built
return try body(head)
}
}
}
func withVaListOfCStrings<R>(_ args: [String], body: (CVaListPointer) -> R) -> R {
return args.withCStrings { cStrings in
withVaList(cStrings, body)
}
}
let argsStr: [String] = ["Test", "Testing", "The test"]
withVaListOfCStrings(argsStr) { listPtr in
test_va_arg_str(Int32(argsStr.count), listPtr)
}
// Output:
// Printing 3 strings...
// Test
// Testing
// The test

Print UTF-32 string with wprintf

I am migrating some code from using wchar_t to char32_t, and when compiling with the -Werror=pointer-sign flag set, I am getting the following issue:
// main.c
#include <uchar.h>
#include <wchar.h>
int main(void) {
wprintf(U"some data\n");
}
Compiling: gcc -std=c11 -Werror=pointer-sign main.c
Output:
main.c: In function ‘main’:
main.c:5:10: error: pointer targets in passing argument 1 of ‘wprintf’ differ in signedness [-Werror=pointer-sign]
wprintf(U"some data\n");
^~~~~~~~~~~~~~
In file included from main.c:2:
/usr/include/wchar.h:587:12: note: expected ‘const wchar_t * restrict’ {aka ‘const int * restrict’} but argument is of type ‘unsigned int *’
extern int wprintf (const wchar_t *__restrict __format, ...)
^~~~~~~
To remedy this, I can do:
wprintf((const int *)U"some data\n");
//or
printf("%ls\n", U"some data");
Although this is quite a pain. Is there a nice and easy way to do this? What is the real difference between const unsigned int* vs const signed int*, aside from the data type it points to? Is this possibly dangerous, or should I just disable the flag altogether?
char32_t is an unsigned type.
wchar_t is either signed or unsigned, depending on implementation. In your case, it is signed.
You can't pass a pointer-to-unsigned where a pointer-to-signed is expected. So yes, you need a type-cast, however you should be casting to const wchar_t *, since that is what wprintf() actually expects (wchar_t just happens to be implemented as an int on your compiler, but don't cast to that directly):
wprintf((const wchar_t *)U"some data\n");
It doesn't get much cleaner than that, unless you wrap it in your own function, eg:
int wprintf32(const char32_t *str, ...)
{
va_list args;
va_start(args, str);
int result = vwprintf((const wchar_t *)str, args);
va_end(args);
return result;
}
wprintf32(U"some data\n");
Note that this code will not work properly at all on platforms where sizeof(wchar_t) < sizeof(char32_t), such as Windows. On those platforms, where sizeof(wchar_t) is 2, you will have to actually convert your string data from UTF-32 to UTF-16 instead, eg:
int wprintf32(const char32_t *str, ...)
{
va_list args;
int result;
va_start(args, str);
if (sizeof(wchar_t) < sizeof(char32_t))
{
wchar_t *str = convert_to_utf16(str); // <-- for you to implement
result = vwprintf(str, args);
free(str);
}
else
result = vwprintf((const wchar_t *)str, args);
va_end(args);
return result;
}
wprintf32(U"some data\n");

In systemverilog is there a way to condition on a type?

So I am using a parameterized type in a common module.
Is there a way to say:
if( type == TYPE1 ) assign the struct one way
else if( type == TYPE2 ) assign another way
I was picturing this in a generate block.
Yes, you can use the type operator do a generate-if/case, or procedural if/case like:
real r;
if ( type(r) == type(real) ) ...
But unfortunately the code in all branches still must successfully compile, regardless of the condition. You will not be able to reference struct member that does not exist.
typedef struct {int a;} s1_t;
typedef struct {int a;int b;} s2_t;
s1_t s;
initial
#1 // procedural-if
if (type(s) == type(s1_t))
$display("%m s.a = %0d",s.a);
else if (type(s) == type(s2_t))
$display("%m s.b ==%0d",s.b); // this will not compile
There is type() operator described in IEEE1800-2012 § 6.23. Example usage from from the LRM:
bit[12:0] A_bus, B_bus;
parameter typebus_t = type(A_bus);
generate
case(type(bus_t))
type(bit[12:0]): addfixed_int #(bus_t) (A_bus,B_bus);
type(real): add_float #(type(A_bus)) (A_bus,B_bus);
endcase
endgenerate
There is also $typename() described in IEEE1800-2012 § 20.6.1. $typename() return s string of the type. Example usage from from the LRM:
// source code // $typename would return
typedef bitnode; // "bit"
node [2:0] X; // "bit [2:0]"
int signedY; // "int"
packageA;
enum{A,B,C=99} X; // "enum{A=32'sd0,B=32'sd1,C=32'sd99}A::e$1"
typedef bit[9:1'b1] word; // "A::bit[9:1]"
endpackage: A
importA::*;
moduletop;
typedef struct{node A,B;} AB_t;
AB_t AB[10]; // "struct{bit A;bit B;}top.AB_t$[0:9]"
...
endmodule

C How can I write a value to an entire data structure, rather than just an element?

I am attempting to write a little C test program for reading data from a vending machine. I have the circuit hooked up, now the hard part is the code.
The machine uses UART that calls for 9 total data bits. Here is my code. Attempting to write directly to the full 9 bit data type does not work, but writing to an element of it does.
struct nineBit { //To make 9 bit character types for an array.
unsigned int data : 8; //8 data bits.
unsigned int mode : 1; //1 'mode' bit.
} data[35]; //Make an array of 9 bit data to store the incoming data block.
void setup() {
Serial1.begin(9600, SERIAL_9N1); //Start the UART.
}
void loop() {
data[0] = Serial1.read(); //Works if 'data[0].data is entered instead.
//How can I transfer this all in one command?
}
Errors are
rx.cpp: In function 'void loop()':
rx.cpp:11:12: error: no match for 'operator=' (operand types are 'nineBit' and 'int')
void setup() {
^
rx.cpp:11:12: note: candidates are:
rx.cpp:1:8: note: nineBit& nineBit::operator=(const nineBit&)
^
rx.cpp:1:8: note: no known conversion for argument 1 from 'int' to 'const nineBit&'
rx.cpp:1:8: note: nineBit& nineBit::operator=(nineBit&&)
rx.cpp:1:8: note: no known conversion for argument 1 from 'int' to 'nineBit&&'
make[1]: *** [../build/target/user/platform-6rx.o] Error 1
make: *** [user] Error 2
Error: Could not compile. Please review your code.
I assume you are using arduino or something similar. So Serial1.read() returns char. char is a signed 1 byte (8 bits) field. And your struct nineBit has 9 bits. How do you expect of writing 8 bits to 9 bited structure?
A note about your structure: it doesn't have size equal 9 bits. Instance of any variable can have size evaluated in bytes only. So if you want to store 9 bits you have to create a two byted structure or more.
And in fact sizeof(nineBit) equals 4 because your bit field have unsigned int type. If you want to reduce size of your structure you have to change bit field type to either short or char.
Let's assume your serial transports two bytes per every structure. So you have to read two bytes and then assign them:
struct nineBit {
char data : 8; //8 data bits.
char mode : 1; //1 'mode' bit.
} data[35];
void setup() {
Serial1.begin(9600, SERIAL_9N1); //Start the UART.
}
void loop() {
char byte1=Serial1.read();
char byte2=Serial1.read();
data[0].data=byte1;
data[0].mode=byte2;
}
If you want to use only a single line you have to write a C function or overload operator= if you use C++.
C way
struct nineBit {
char data : 8; //8 data bits.
char mode : 1; //1 'mode' bit.
} data[35];
void writeToNineBit(struct nineBit *value){
char byte1=Serial1.read();
char byte2=Serial1.read();
value->data=byte1;
value->mode=byte2;
}
void setup() {
Serial1.begin(9600, SERIAL_9N1); //Start the UART.
}
void loop() {
writeToNineBit(data+0); // or &data[0].. 0 is an index in array..
}
C++ way
struct nineBit {
char data : 8; //8 data bits.
char mode : 1; //1 'mode' bit.
// assume you have to assign data without mode..
nineBit& operator=(char b){
this->data=b;
}
} data[35];
void setup() {
Serial1.begin(9600, SERIAL_9N1); //Start the UART.
}
void loop() {
data[0]=Serial1.read(); // now it works cause you have operator overloading in your structure..
}

Why we used double and triple pointer in objective-C or C language?

I confused when i want to take single pointer and when should i take double pointer?
In following structure what exactly did?
struct objc_class {
Class isa;
Class super_class;
const char *name;
long version;
long info;
long instance_size;
struct objc_ivar_list *ivars;
struct objc_method_list **methodLists;
struct objc_cache *cache;
struct objc_protocol_list *protocols;
};
Why we use the methodLists double pointer?
Edited
int sqlite3_get_table(
sqlite3 *db,
const char *zSql,
char ***pazResult,
int *pnRow,
int *pnColumn,
char **pzErrmsg
);
In above scenario what will be meaning of triple pointer char ***pazResult?
Well, in C at least, double-pointers are commonly used for 2D arrays. The most common 2D array is probably an array of C strings (char*'s). Double pointers are also sometimes employed to pass pointers to functions by reference, but this is unlikely to be the use in the code sample you posted.
According to the name methodLists I would guess that this is an array of lists. A (linked) list in C is commonly represented by a pointer to a node, which objc_method_list could be. An array of such lists is then implemented with a double pointer.
It's probably not the case in the code that you referenced, but you also need a double pointer any time you want to pass a pointer to a function and have changes to that pointer be reflected outside the scope of that function.
For example, if you were trying to rewrite the strcpy function so that the user did not have to allocate memory for the source string, you might try something like the following:
void MyStrcpy(char* dst, char* src){
dst = (char*)malloc(sizeof(char)*(strlen(src)+1));
for(int i=0;i<=strlen(src);i++)
dst[i] = src[i];
printf("src: %s ", src);
printf("dst: %s\n\n", dst);
}
If you were then to call that function,
int main() {
char *foo = "foo";
char *newPtr;
MyStrcpy(newPtr, foo);
printf("foo: %s ", foo);
printf("new: %s\n", newPtr);
}
your output would be as follows:
src: foo
dst: foo
foo: foo
new:
You might also get a seg fault when trying to print newPtr, depending your system. The reason for this behavior is the exact same as the reason you wouldn't expect a change to an int that was passed by value to a function to be reflected outside of that function: what you are passing to MyStrcpy is simply the memory address that newPtr references. When you malloc the space for dst inside the function, you are changing the address dst points to. This change will not be reflected outside of the scope of MyStrcpy!
Instead, if you wanted newPtr to point to the new allocated chunk of memory, you need to have dst be a pointer to a pointer, a char **.
void MyStrcpy(char** dst, char* src){
*dst = (char*)malloc(sizeof(char)*(strlen(src)+1));
for(int i=0;i<=strlen(src);i++)
(*dst)[i] = src[i];
printf("src: %s ", src);
printf("dst: %s\n\n", *dst);
}
Now, if you were to call that function:
int main() {
char *foo = "foo";
char *newPtr;
MyStrcpy(&newPtr, foo);
printf("foo: %s ", foo);
printf("new: %s\n", newPtr);
}
You would get your expected output:
src: foo
dst: foo
foo: foo
new: foo
Hope that helps!
See also these questions:
What is double star?
Why does NSError need double indirection? (pointer to a pointer)
In the most general case a double pointer is a pointer to a list of pointers.
In general pointer is used to hold the address of another variable. What if we need to hold the address of pointer ,in that case we use double pointer. When we want to hold the address of double pointer we use triple pointer.