jaulib v1.4.0-2-g788cf73
Jau Support Library (C++, Java, ..)
Loading...
Searching...
No Matches
test_darray_01.cpp
Go to the documentation of this file.
1/*
2 * Author: Sven Gothel <sgothel@jausoft.com>
3 * Copyright (c) 2020-2024 Gothel Software e.K.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be
14 * included in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24#include <cassert>
25#include <cstring>
26
27#include <jau/test/catch2_ext.hpp>
28
29#include "test_datatype01.hpp"
30
31#include "test_datatype02.hpp"
32
33#include <jau/basic_algos.hpp>
34#include <jau/basic_types.hpp>
35#include <jau/darray.hpp>
37#include <jau/callocator.hpp>
39
40/**
41 * Test general use of jau::darray, jau::cow_darray and jau::cow_vector.
42 */
43using namespace jau;
44
45/**********************************************************************************************************************************************/
46/**********************************************************************************************************************************************/
47/**********************************************************************************************************************************************/
48/**********************************************************************************************************************************************/
49/**********************************************************************************************************************************************/
50
51TEST_CASE( "JAU DArray Test 01 - jau::darray initializer list", "[datatype][jau][darray]" ) {
52 int i = 0;
54 (void)ml;
55 // printf("XX: %s\n\n", ml->toString().c_str());
56 ++i;
57 });
58 REQUIRE(3 == i);
59}
60
62 int i = 0;
63 jau::for_each(clist.begin(), clist.end(), [&i](const GattCharacteristicSpec& ml){
64 (void)ml;
65 // printf("XX: %s\n\n", ml->toString().c_str());
66 ++i;
67 });
68 return i;
69}
71 int i = 0;
72 jau::for_each(clist.begin(), clist.end(), [&i](const GattCharacteristicSpec& ml){
73 (void)ml;
74 // printf("XX: %s\n\n", ml->toString().c_str());
75 ++i;
76 });
77 return i;
78}
79
80// NOLINTBEGIN(modernize-use-designated-initializers)
81TEST_CASE( "JAU DArray Test 02 - jau::darray immutable type (const)", "[const][jau][darray]" ) {
83 // GattCharacteristicPropertySpec[9]:
84 { { Read, Mandatory },
87 // GattClientCharacteristicConfigSpec:
89 };
91 cs1,
93 // GattCharacteristicPropertySpec[9]:
94 { { Read, Mandatory },
97 // GattClientCharacteristicConfigSpec:
99 } };
100 clist.push_back( cs1 );
101 int i = 0;
102 jau::for_each(clist.begin(), clist.end(), [&i](const GattCharacteristicSpec& ml){
103 (void)ml;
104 // printf("XX: %s\n\n", ml->toString().c_str());
105 ++i;
106 });
107 REQUIRE(3 == i);
109 REQUIRE(3 == countGattCharacteristicSpecList02Copy(clist));
110}
111// NOLINTEND(modernize-use-designated-initializers)
112
113/**********************************************************************************************************************************************/
114/**********************************************************************************************************************************************/
115/**********************************************************************************************************************************************/
116/**********************************************************************************************************************************************/
117/**********************************************************************************************************************************************/
118
119template<class Payload>
121
122template<class Payload>
124
125template<class Payload>
127 int name;
129
130 std::string toString() const noexcept {
131 std::string res = "NSPL-Default-"+std::to_string(name)+"[sz "+std::to_string(payload.size())+"/"+std::to_string(payload.capacity())+": ";
132 int i=0;
133 jau::for_each(payload.cbegin(), payload.cend(), [&](const std::shared_ptr<Payload>& e) {
134 if(0<i) {
135 res.append(", ");
136 }
137 res.append("[").append(jau::to_string(e)).append("]");
138 ++i;
139 } );
140 res.append("]");
141 return res;
142 }
143};
144
145template<class Payload>
147 int name;
149
150 std::string toString() const noexcept {
151 std::string res = "NSPL-MemMove-"+std::to_string(name)+"[sz "+std::to_string(payload.size())+"/"+std::to_string(payload.capacity())+": ";
152 int i=0;
153 jau::for_each(payload.cbegin(), payload.cend(), [&](const std::shared_ptr<Payload>& e) {
154 if(0<i) {
155 res.append(", ");
156 }
157 res.append("[").append(jau::to_string(e)).append("]");
158 ++i;
159 } );
160 res.append("]");
161 return res;
162 }
163};
164
165template<class Payload>
167
168template<class Payload>
170
171template<class Payload>
173 int name;
175
176 std::string toString() const noexcept {
177 std::string res = "NPL-Default-"+std::to_string(name)+"[sz "+std::to_string(payload.size())+"/"+std::to_string(payload.capacity())+": ";
178 int i=0;
179 jau::for_each(payload.cbegin(), payload.cend(), [&](const typename PayloadListDefault<Payload>::value_type & e) {
180 if(0<i) {
181 res += ", ";
182 }
183 res.append("[").append(jau::to_string(e)).append("]");
184 ++i;
185 } );
186 res += "]";
187 return res;
188 }
189};
190
191template<class Payload>
193 int name;
195
196 std::string toString() const noexcept {
197 std::string res = "NPL-MemMove-"+std::to_string(name)+"[sz "+std::to_string(payload.size())+"/"+std::to_string(payload.capacity())+": ";
198 int i=0;
199 jau::for_each(payload.cbegin(), payload.cend(), [&](const Payload& e) {
200 if(0<i) {
201 res += ", ";
202 }
203 res.append("[").append(jau::to_string(e)).append("]");
204 ++i;
205 } );
206 res += "]";
207 return res;
208 }
209};
210
211template<class Payload>
214 int i=0;
215 for(i=0; i<2; i++) {
216 std::shared_ptr<Payload> sp(std::make_shared<Payload>( name+i )); // copy-elision + make_shared in-place
217 data.push_back( sp );
218 }
219 CHECK( 2 == data.size() );
220 for(i=2; i<4; i++) {
221 std::shared_ptr<Payload> sp(new Payload( name+i )); // double malloc: 1 Payload, 2 shared_ptr
222 data.push_back( std::move( sp ) ); // move the less efficient into
223 }
224 CHECK( 4 == data.size() );
226}
227template<class Payload>
229 printf("XXX1: %s\n", src.toString().c_str());
230 const size_t sz0 = src.payload.size();
231 src.payload.pop_back();
232 src.payload.erase(src.payload.cbegin());
233 CHECK( sz0 - 2 == src.payload.size() );
234 printf("XXX2: %s\n", src.toString().c_str());
235 return src;
236}
237
238template<class Payload>
241 int i=0;
242 for(i=0; i<2; i++) {
243 std::shared_ptr<Payload> sp(std::make_shared<Payload>( name+i )); // copy-elision + make_shared in-place
244 data.push_back( sp );
245 }
246 CHECK( 2 == data.size() );
247 for(i=2; i<4; i++) {
248 std::shared_ptr<Payload> sp(new Payload( name+i )); // double malloc: 1 Payload, 2 shared_ptr
249 data.push_back( std::move( sp ) ); // move the less efficient into
250 }
251 CHECK( 4 == data.size() );
253}
254template<class Payload>
257 int i=0;
258 for(i=0; i<2; i++) {
259 Payload sp( name+i ); // copy-elision
260 data.push_back( sp );
261 }
262 CHECK( 2 == data.size() );
263 for(i=2; i<4; i++) {
264 Payload sp( name+i );
265 data.push_back( std::move( sp ) ); // move the less efficient into
266 }
267 CHECK( 4 == data.size() );
269}
270template<class Payload>
273 int i=0;
274 for(i=0; i<2; i++) {
275 Payload sp( name+i ); // copy-elision
276 data.push_back( sp );
277 }
278 CHECK( 2 == data.size() );
279 for(i=2; i<4; i++) {
280 Payload sp( name+i );
281 data.push_back( std::move( sp ) ); // move the less efficient into
282 }
283 CHECK( 4 == data.size() );
285}
286
287#define CHECK_TRAITS 0
288
289template< class Cont >
290static void print_container_info(const std::string& type_id, const Cont &c,
291 std::enable_if_t< jau::is_darray_type<Cont>::value, bool> = true )
292{
293 printf("\nContainer Type %s (a darray, a cow %d):\n - Uses memmove %d (trivially_copyable %d); realloc %d; base_of jau::callocator %d; secmem %d; size %d bytes\n",
294 type_id.c_str(), jau::is_cow_type<Cont>::value,
295 Cont::uses_memmove,
296 std::is_trivially_copyable_v<typename Cont::value_type>,
297 Cont::uses_realloc,
298 std::is_base_of_v<jau::callocator<typename Cont::value_type>, typename Cont::allocator_type>,
299 Cont::uses_secmem,
300 (int)sizeof(c));
301}
302
303template<class Cont>
304static void print_container_info(const std::string& type_id, const Cont &c,
305 std::enable_if_t< !jau::is_darray_type<Cont>::value, bool> = true )
306{
307 printf("\nContainer Type %s (!darray, a cow %d); size %d bytes\n",
308 type_id.c_str(), jau::is_cow_type<Cont>::value, (int)sizeof(c));
309}
310
311
312template<class Payload>
313static void testDArrayValueType(const std::string& type_id) {
314 {
315 // jau::type_cue<Payload>::print(type_id, jau::TypeTraitGroup::ALL);
316 // jau::type_cue<std::shared_ptr<Payload>>::print("std::shared_ptr<"+type_id+">", jau::TypeTraitGroup::ALL);
317 }
318 {
319#if CHECK_TRAITS
320 CHECK( true == std::is_base_of<jau::callocator<Payload>, jau::callocator<Payload>>::value);
322 CHECK( true == std::is_trivially_copyable<Payload>::value);
324#endif
325
327 print_container_info("NamedPayloadListDefault<"+type_id+">", data.payload);
328 size_t sz0 = data.payload.size();
329 printf("COPY-0.0: %s\n\n", data.toString().c_str());
330 CHECK( sz0 == data.payload.capacity() );
331
332 {
333 Payload def_value(1);
335 printf("COPY-0.1: %s\n\n", data2.toString().c_str());
336 CHECK( 0 == data2.payload.size() );
337 CHECK( 0 == data2.payload.capacity() );
338 data2.payload.reserve(2);
339 printf("COPY-0.1a: %s\n\n", data2.toString().c_str());
340 CHECK( 0 == data2.payload.size() );
341 CHECK( 2 == data2.payload.capacity() );
342 data2.payload.resize(2, def_value);
343 printf("COPY-0.1b: %s\n\n", data2.toString().c_str());
344 CHECK( 2 == data2.payload.size() );
345 CHECK( 2 == data2.payload.capacity() );
346 for(Payload p : data2.payload) {
347 CHECK(def_value == p);
348 }
349 data2.payload.resize(4, def_value);
350 printf("COPY-0.2: %s\n\n", data2.toString().c_str());
351 CHECK( 4 == data2.payload.size() );
352 CHECK( 4 == data2.payload.capacity() );
353 for(Payload p : data2.payload) {
354 CHECK(def_value == p);
355 }
356
357 data2.payload.erase(data2.payload.cbegin());
358 printf("COPY-0.3: %s\n\n", data2.toString().c_str());
359 CHECK( 3 == data2.payload.size() );
360 CHECK( sz0 == data2.payload.capacity() );
361
362 data2.payload.shrink_to_fit();
363 printf("COPY-0.4: %s\n\n", data2.toString().c_str());
364 CHECK( 3 == data2.payload.size() );
365 CHECK( 3 == data2.payload.capacity() );
366 }
367 {
368 Payload def_value(1);
370 printf("COPY-1.0: %s\n\n", data2.toString().c_str());
371 CHECK( sz0 == data2.payload.size() );
372 CHECK( sz0 == data2.payload.capacity() );
373 data2.payload.erase(data2.payload.cbegin());
374 printf("COPY-1.1: %s\n\n", data2.toString().c_str());
375 CHECK( sz0-1 == data2.payload.size() );
376 CHECK( sz0 == data2.payload.capacity() );
377 data2.payload.resize(sz0, def_value);
378 printf("COPY-1.2: %s\n\n", data2.toString().c_str());
379 CHECK( sz0 == data2.payload.size() );
380 CHECK( sz0 == data2.payload.capacity() );
381 size_t j=0;
382 for(Payload p : data2.payload) {
383 if( j++ < sz0-1 ) {
384 CHECK(def_value != p);
385 } else {
386 CHECK(def_value == p);
387 }
388 }
389 data2.payload.resize(sz0*2, def_value);
390 printf("COPY-1.2: %s\n\n", data2.toString().c_str());
391 CHECK( sz0*2 == data2.payload.size() );
392 CHECK( sz0*2 == data2.payload.capacity() );
393 j=0;
394 for(Payload p : data2.payload) {
395 if( j++ < sz0-1 ) {
396 CHECK(def_value != p);
397 } else {
398 CHECK(def_value == p);
399 }
400 }
401 }
402 {
403 Payload def_value(1);
405 printf("COPY-2.0: %s\n\n", data3.toString().c_str());
406 CHECK( sz0 == data3.payload.size() );
407 CHECK( sz0 == data3.payload.capacity() );
408 data3.payload.erase(data3.payload.begin(), data3.payload.cbegin()+data3.payload.size()/2);
409 printf("COPY-2.1: %s\n\n", data3.toString().c_str());
410 CHECK( sz0/2 == data3.payload.size() );
411 CHECK( sz0 == data3.payload.capacity() );
412 data3.payload.resize(sz0, def_value);
413 printf("COPY-2.2: %s\n\n", data3.toString().c_str());
414 CHECK( sz0 == data3.payload.size() );
415 CHECK( sz0 == data3.payload.capacity() );
416 size_t j=0;
417 for(Payload p : data3.payload) {
418 if( j++ < sz0/2 ) {
419 CHECK(def_value != p);
420 } else {
421 CHECK(def_value == p);
422 }
423 }
424 data3.payload.resize(sz0*2, def_value);
425 printf("COPY-2.3: %s\n\n", data3.toString().c_str());
426 CHECK( sz0*2 == data3.payload.size() );
427 CHECK( sz0*2 == data3.payload.capacity() );
428 j=0;
429 for(Payload p : data3.payload) {
430 if( j++ < sz0/2 ) {
431 CHECK(def_value != p);
432 } else {
433 CHECK(def_value == p);
434 }
435 }
436 }
437 {
439 CHECK( sz0 == data8.payload.size() );
440 data8.payload.insert(data8.payload.begin(), data.payload.cbegin(), data.payload.cend());
441 CHECK( 2*sz0 == data8.payload.size() );
442 printf("COPY+2: %s\n\n", data8.toString().c_str());
443 }
444 }
445 {
446#if CHECK_TRAITS
447 CHECK( true == std::is_base_of<jau::callocator<Payload>, jau::callocator<Payload>>::value);
449 CHECK( true == std::is_trivially_copyable<Payload>::value);
451#endif
452
454 print_container_info("NamedPayloadListMemMove<"+type_id+">", data.payload);
455
457 data2.payload.erase(data2.payload.cbegin());
458
460 data3.payload.erase(data3.payload.begin(), data3.payload.cbegin()+data3.payload.size()/2);
461
463 data8.payload.insert(data8.payload.begin(), data.payload.cbegin(), data.payload.cend());
464
465 printf("COPY-0: %s\n\n", data.toString().c_str());
466 printf("COPY-1: %s\n\n", data2.toString().c_str());
467 printf("COPY-2: %s\n\n", data3.toString().c_str());
468 printf("COPY+2: %s\n\n", data8.toString().c_str());
469 }
470 {
471#if CHECK_TRAITS
472 CHECK( true == std::is_base_of<jau::callocator<std::shared_ptr<Payload>>, jau::callocator<std::shared_ptr<Payload>>>::value);
474 CHECK( true == std::is_trivially_copyable<std::shared_ptr<Payload>>::value);
476#endif
477
479 print_container_info("NamedSharedPayloadListDefault<"+type_id+">", data.payload);
480
482 data2.payload.erase(data2.payload.cbegin());
483
485 data3.payload.erase(data3.payload.begin(), data3.payload.cbegin()+data3.payload.size()/2);
486
488 data8.payload.insert(data8.payload.begin(), data.payload.cbegin(), data.payload.cend());
489
490 printf("COPY-0: %s\n\n", data.toString().c_str());
491 printf("COPY-1: %s\n\n", data2.toString().c_str());
492 printf("COPY-2: %s\n\n", data3.toString().c_str());
493 printf("COPY+2: %s\n\n", data8.toString().c_str());
494
496 printf("MODI+2-2: %s\n\n", data8_mod.toString().c_str());
497
498 struct Holder {
500 NamedSharedPayloadListDefault<Payload> & get_ref() { return lala; }
501 NamedSharedPayloadListDefault<Payload> & get_ref2() { lala.payload.pop_back(); return lala; }
502 NamedSharedPayloadListDefault<Payload> get_copy() { return lala; }
503 };
504 Holder holder{ data };
505 NamedSharedPayloadListDefault<Payload> & r1r1 = holder.get_ref();
506 printf("R1R1: %s\n\n", r1r1.toString().c_str());
507
508 NamedSharedPayloadListDefault<Payload> r2c1 = holder.get_ref();
509 printf("R1C1: %s\n\n", r2c1.toString().c_str());
510
511 NamedSharedPayloadListDefault<Payload> c1c2 = holder.get_copy();
512 printf("C1C2: %s\n\n", c1c2.toString().c_str());
513
514 r1r1 = holder.get_ref2();
515 printf("R2R2: %s\n\n", r1r1.toString().c_str());
516 }
517 {
518#if CHECK_TRAITS
519 CHECK( true == std::is_base_of<jau::callocator<std::shared_ptr<Payload>>, jau::callocator<std::shared_ptr<Payload>>>::value);
521 CHECK( true == std::is_trivially_copyable<std::shared_ptr<Payload>>::value);
523#endif
524
526 print_container_info("NamedSharedPayloadListMemMove<"+type_id+">", data.payload);
527
529 data2.payload.erase(data2.payload.cbegin());
530
532 data3.payload.erase(data3.payload.begin(), data3.payload.cbegin()+data3.payload.size()/2);
533
535 data8.payload.insert(data8.payload.begin(), data.payload.cbegin(), data.payload.cend());
536
537 printf("COPY-0: %s\n\n", data.toString().c_str());
538 printf("COPY-1: %s\n\n", data2.toString().c_str());
539 printf("COPY-2: %s\n\n", data3.toString().c_str());
540 printf("COPY+2: %s\n\n", data8.toString().c_str());
541 }
542}
543
545 return *GATT_SERVICES[i];
546}
547
549#if CHECK_TRAITS
551 CHECK( true == GattCharacteristicSpecList::uses_realloc);
552
553 CHECK( true == GattCharacteristicSpecList::uses_memmove);
554 CHECK( true == std::is_trivially_copyable<GattCharacteristicSpec>::value);
555#endif
556
558 print_container_info("darray<GattCharacteristicSpec>", gatt2.characteristics);
559
561
562 GattServiceCharacteristic gatt2b = gatt2;
564
565 GattServiceCharacteristic gatt2c(gatt2);
567
568 printf("COPY0-1: %s\n\n", gatt2.toString().c_str());
569 printf("COPY1-2: %s\n\n", gatt2b.toString().c_str());
570 printf("COPY2-3: %s\n\n", gatt2c.toString().c_str());
571}
572
573TEST_CASE( "JAU DArray Test 10 - jau::darray value_type behavior (type traits)", "[datatype][jau][darray]" ) {
579}
580
581/**********************************************************************************************************************************************/
582/**********************************************************************************************************************************************/
583/**********************************************************************************************************************************************/
584/**********************************************************************************************************************************************/
585/**********************************************************************************************************************************************/
586
Implementation of a dynamic linear array storage, aka vector, including relative positional access.
Definition darray.hpp:153
constexpr iterator erase(const_iterator cpos)
Like std::vector::erase(), removes the elements at pos.
Definition darray.hpp:1318
constexpr iterator end() noexcept
Definition darray.hpp:828
constexpr size_type size() const noexcept
Like std::vector::size().
Definition darray.hpp:1069
constexpr void push_back(const value_type &x)
Like std::vector::push_back(), copy.
Definition darray.hpp:1522
constexpr const_iterator cbegin() const noexcept
Definition darray.hpp:826
constexpr iterator begin() noexcept
Definition darray.hpp:824
static constexpr const bool uses_realloc
Definition darray.hpp:160
static constexpr const bool uses_memmove
Definition darray.hpp:158
constexpr UnaryFunction for_each(InputIt first, InputIt last, UnaryFunction f)
Like std::for_each() of 'algorithm'.
constexpr bool value(const Bool rhs) noexcept
constexpr std::string_view name(const Bool v) noexcept
uint_fast32_t nsize_t
Natural 'size_t' alternative using uint_fast32_t as its natural sized type.
Definition int_types.hpp:55
__pack(...): Produces MSVC, clang and gcc compatible lead-in and -out macros.
Definition backtrace.hpp:32
std::string to_string(const bit_order_t v) noexcept
Return std::string representation of the given bit_order_t.
std::string toString() const noexcept
jau::darray< GattCharacteristicSpec > characteristics
PayloadListDefault< Payload > payload
std::string toString() const noexcept
PayloadListMemMove< Payload > payload
std::string toString() const noexcept
std::string toString() const noexcept
SharedPayloadListDefault< Payload > payload
std::string toString() const noexcept
SharedPayloadListMemMove< Payload > payload
A simple allocator using POSIX C functions: ::malloc(), ::free() and ::realloc().
template< class T > is_cow_type<T>::value compile-time Type Trait, determining whether the given temp...
template< class T > is_darray_type<T>::value compile-time Type Trait, determining whether the given t...
Definition darray.hpp:1916
static int countGattCharacteristicSpecList01ConstRef(const jau::darray< const GattCharacteristicSpec > &clist)
static NamedSharedPayloadListDefault< Payload > makeNamedSharedPayloadListDefault(int name)
jau::darray< Payload, jau::nsize_t, jau::callocator< Payload >, true > PayloadListMemMove
static NamedSharedPayloadListMemMove< Payload > makeNamedSharedPayloadListMemMove(int name)
static void print_container_info(const std::string &type_id, const Cont &c, std::enable_if_t< jau::is_darray_type< Cont >::value, bool >=true)
static void testDArrayValueType(const std::string &type_id)
static NamedPayloadListDefault< Payload > makeNamedPayloadListDefault(int name)
static GattServiceCharacteristic returnGattSrvcChar(int i)
jau::darray< std::shared_ptr< Payload > > SharedPayloadListDefault
static NamedPayloadListMemMove< Payload > makeNamedPayloadListMemMove(int name)
TEST_CASE("JAU DArray Test 01 - jau::darray initializer list", "[datatype][jau][darray]")
static NamedSharedPayloadListDefault< Payload > modifyCopyOfNamedSharedPayloadListDefault(NamedSharedPayloadListDefault< Payload > src)
jau::darray< Payload > PayloadListDefault
static int countGattCharacteristicSpecList02Copy(jau::darray< const GattCharacteristicSpec > clist)
static void testDArrayGattServiceCharacteristic()
jau::darray< std::shared_ptr< Payload >, jau::nsize_t, jau::callocator< std::shared_ptr< Payload > >, true > SharedPayloadListMemMove
const jau::darray< const GattServiceCharacteristic * > GATT_SERVICES
@ ReliableWriteExt
FIXME: extension?
@ Indicate
@ AuthSignedWrite
@ WriteNoAck
@ Broadcast
@ AuxWriteExt
FIXME: extension?
@ WriteWithAck
@ Optional
@ Mandatory
@ Excluded
@ DEVICE_NAME
@ APPEARANCE
int printf(const char *format,...)
Operating Systems predefined macros.